@rapidmx/web-client 0.15.1 → 0.17.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 (318) hide show
  1. package/README.md +381 -373
  2. package/apps/admin/branding/index.tsx +39 -39
  3. package/apps/admin/data-requests/index.tsx +482 -480
  4. package/apps/admin/distribution-lists/new/index.tsx +3 -1
  5. package/apps/admin/domains/[uid].tsx +166 -164
  6. package/apps/admin/domains/new/index.tsx +3 -1
  7. package/apps/admin/escrow-scopes/[uid].tsx +350 -348
  8. package/apps/admin/escrow-scopes/new/index.tsx +3 -1
  9. package/apps/admin/index.tsx +129 -124
  10. package/apps/admin/mailboxes/[uid].tsx +271 -224
  11. package/apps/admin/mailboxes/new/index.tsx +30 -28
  12. package/apps/admin/plugins/index.tsx +15 -15
  13. package/apps/admin/retention-policy/index.tsx +39 -39
  14. package/apps/admin/signing-certificates/index.tsx +343 -343
  15. package/apps/admin/transport-rules/new/index.tsx +3 -1
  16. package/apps/escrow/audit-log/index.tsx +196 -196
  17. package/apps/escrow/matters/[uid].tsx +621 -621
  18. package/apps/escrow/matters/new/index.tsx +3 -1
  19. package/apps/shared/auth/adminAccess.ts +99 -99
  20. package/apps/shared/components/admin/layout/AdminShell.tsx +381 -378
  21. package/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.tsx +238 -0
  22. package/apps/shared/components/admin/mailboxes/EscrowScopeCard.tsx +152 -152
  23. package/apps/shared/components/admin/mailboxes/LeftoverMailboxesSection.tsx +194 -0
  24. package/apps/shared/components/admin/settings/BrandingForm.tsx +423 -423
  25. package/apps/shared/components/admin/settings/EncryptionPolicyForm.tsx +119 -119
  26. package/apps/shared/components/admin/settings/MailboxCreateForm.tsx +50 -3
  27. package/apps/shared/components/admin/settings/MailboxPolicyForm.tsx +198 -198
  28. package/apps/shared/components/admin/settings/PluginsManager.tsx +1545 -1545
  29. package/apps/shared/components/admin/settings/RetentionPolicyForm.tsx +182 -182
  30. package/apps/shared/components/admin/setup/EscrowSetupStep.tsx +288 -288
  31. package/apps/shared/components/admin/setup/SetupWizard.tsx +446 -444
  32. package/apps/shared/components/admin/usePagedList.tsx +129 -129
  33. package/apps/shared/components/calendar/EventEditor.tsx +5 -10
  34. package/apps/shared/components/calendar/EventFormParts.tsx +16 -47
  35. package/apps/shared/components/calendar/EventModal.tsx +206 -206
  36. package/apps/shared/components/calendar/GuestInput.tsx +100 -0
  37. package/apps/shared/components/calendar/MonthView.tsx +185 -185
  38. package/apps/shared/components/calendar/RecurrenceEditor.tsx +227 -227
  39. package/apps/shared/components/calendar/RequestChangeForm.tsx +23 -54
  40. package/apps/shared/components/calendar/SplitDayView.tsx +144 -144
  41. package/apps/shared/components/calendar/TimeGridView.tsx +246 -246
  42. package/apps/shared/components/calendar/allDay.ts +124 -124
  43. package/apps/shared/components/calendar/eventForm.ts +2 -2
  44. package/apps/shared/components/calendar/eventFormat.ts +49 -22
  45. package/apps/shared/components/calendar/layout/CalendarShell.tsx +201 -200
  46. package/apps/shared/components/contacts/ContactForm.tsx +383 -383
  47. package/apps/shared/components/contacts/ContactsSidebar.tsx +1 -1
  48. package/apps/shared/components/contacts/ContactsToolbar.tsx +103 -98
  49. package/apps/shared/components/contacts/layout/ContactsShell.tsx +218 -216
  50. package/apps/shared/components/escrow/layout/EscrowShell.tsx +155 -155
  51. package/apps/shared/components/layout/AppShell.tsx +461 -480
  52. package/apps/shared/components/layout/FloatingActionButton.tsx +31 -0
  53. package/apps/shared/components/layout/KeyEnrollmentGate.tsx +398 -398
  54. package/apps/shared/components/layout/MailboxProvisioning.tsx +168 -168
  55. package/apps/shared/components/layout/ResponsiveToolbar.tsx +315 -315
  56. package/apps/shared/components/layout/ThemeSwitch.tsx +84 -84
  57. package/apps/shared/components/layout/UserMenu.tsx +439 -424
  58. package/apps/shared/components/mail/ConversationList.tsx +323 -323
  59. package/apps/shared/components/mail/ConversationThreadPane.tsx +613 -491
  60. package/apps/shared/components/mail/EmptyFolderBar.tsx +41 -0
  61. package/apps/shared/components/mail/MailSelectionBar.tsx +240 -227
  62. package/apps/shared/components/mail/MenuButton.tsx +31 -11
  63. package/apps/shared/components/mail/MessageDetailPane.tsx +1757 -1559
  64. package/apps/shared/components/mail/PermanentDeleteDialog.tsx +47 -0
  65. package/apps/shared/components/mail/compose/ComposeContext.tsx +312 -312
  66. package/apps/shared/components/mail/compose/ComposeToolbar.tsx +422 -422
  67. package/apps/shared/components/mail/compose/ComposeWindow.tsx +1681 -1677
  68. package/apps/shared/components/mail/compose/RecipientInput.tsx +54 -11
  69. package/apps/shared/components/mail/compose/RichTextEditor.tsx +147 -147
  70. package/apps/shared/components/mail/compose/composeFlushRegistry.ts +60 -60
  71. package/apps/shared/components/mail/compose/quotedBody.ts +161 -161
  72. package/apps/shared/components/mail/layout/FolderBadgeChip.tsx +21 -0
  73. package/apps/shared/components/mail/layout/MailShell.tsx +161 -134
  74. package/apps/shared/components/mail/layout/SidebarSection.tsx +66 -0
  75. package/apps/shared/components/mail/reading/MessageMoreMenu.tsx +258 -0
  76. package/apps/shared/components/mail/reading/MessageSourceDialog.tsx +79 -0
  77. package/apps/shared/components/mail/reading/PendingMessageCard.tsx +68 -0
  78. package/apps/shared/components/mail/reading/messageExport.ts +59 -0
  79. package/apps/shared/components/mail/reading/printMessage.ts +99 -0
  80. package/apps/shared/components/mail/reading/useMessageActions.ts +443 -0
  81. package/apps/shared/components/mail/verificationSeals.ts +125 -125
  82. package/apps/shared/components/rules/RuleBuilder.tsx +311 -311
  83. package/apps/shared/components/settings/SigningCertificateCard.tsx +344 -344
  84. package/apps/shared/components/settings/layout/SettingsShell.tsx +257 -254
  85. package/apps/shared/components/tasks/TasksSidebar.tsx +1 -1
  86. package/apps/shared/components/tasks/layout/TasksShell.tsx +219 -217
  87. package/apps/shared/keyboard/GlobalShortcuts.tsx +51 -51
  88. package/apps/shared/keyboard/ShortcutProvider.tsx +62 -62
  89. package/apps/shared/keyboard/ShortcutsDialog.tsx +84 -84
  90. package/apps/shared/keyboard/dispatch.ts +124 -124
  91. package/apps/shared/keyboard/format.ts +89 -89
  92. package/apps/shared/keyboard/keymap.ts +114 -114
  93. package/apps/shared/keyboard/registry.ts +65 -65
  94. package/apps/shared/keyboard/targets.ts +79 -79
  95. package/apps/shared/mail/folderCounts.ts +17 -0
  96. package/apps/shared/mail/folderOfType.ts +49 -0
  97. package/apps/shared/mail/folderTree.ts +143 -143
  98. package/apps/shared/mail/listAllPages.ts +39 -39
  99. package/apps/shared/mail/newMailNotifications.ts +171 -171
  100. package/apps/shared/mail/outbox/outgoingReplies.ts +192 -0
  101. package/apps/shared/mail/outbox/sendJob.ts +19 -1
  102. package/apps/shared/mail/outbox/sendOutcomes.ts +13 -4
  103. package/apps/shared/mail/permanentDelete.ts +160 -0
  104. package/apps/shared/mail/primaryMailbox.ts +71 -0
  105. package/apps/shared/mail/reportNotices.ts +66 -0
  106. package/apps/shared/mail/senderBlocking.ts +141 -0
  107. package/apps/shared/mail/useCollapsedSections.ts +146 -0
  108. package/apps/shared/mail/useMailConnection.ts +205 -203
  109. package/apps/shared/mail/useMailLiveUpdates.ts +277 -277
  110. package/apps/shared/mail/useMailboxUpdateAccess.ts +60 -0
  111. package/apps/shared/mail/useMarkMessageRead.ts +47 -47
  112. package/apps/shared/mail/useNewMailNotifications.ts +178 -178
  113. package/apps/shared/mail/usePermanentDelete.tsx +160 -0
  114. package/apps/shared/navigation/frameContext.tsx +1 -1
  115. package/apps/shared/navigation/index.ts +43 -0
  116. package/apps/shared/navigation/pageTitle.ts +19 -0
  117. package/apps/shared/notifications/store.ts +560 -560
  118. package/apps/shared/search/LocalIndexLifecycle.tsx +114 -114
  119. package/apps/shared/search/crossMailboxSearch.ts +169 -0
  120. package/apps/shared/search/localIndexBuilder.ts +481 -481
  121. package/apps/shared/signing/enrollmentStorage.ts +33 -33
  122. package/apps/shared/signing/enrollmentTracker.ts +385 -385
  123. package/apps/shared/signing/enrollmentView.ts +251 -251
  124. package/apps/shared/signing/useNow.ts +19 -19
  125. package/apps/shared/signing/useSigningEnrollmentWatcher.ts +90 -90
  126. package/apps/shared/styles/app.css +396 -386
  127. package/apps/www/_shell.tsx +82 -0
  128. package/apps/www/calendar/index.tsx +581 -571
  129. package/apps/www/contacts/[uid].tsx +112 -109
  130. package/apps/www/contacts/index.tsx +14 -3
  131. package/apps/www/index.tsx +2962 -2479
  132. package/apps/www/messages/[uid].tsx +139 -135
  133. package/apps/www/settings/appearance/index.tsx +5 -2
  134. package/apps/www/settings/auto-reply/index.tsx +136 -133
  135. package/apps/www/settings/blocked-senders/index.tsx +303 -0
  136. package/apps/www/settings/encryption/index.tsx +1290 -1287
  137. package/apps/www/settings/filters/[uid].tsx +179 -176
  138. package/apps/www/settings/filters/index.tsx +105 -102
  139. package/apps/www/settings/filters/new/index.tsx +165 -140
  140. package/apps/www/settings/labels/index.tsx +207 -204
  141. package/apps/www/settings/privacy/index.tsx +495 -492
  142. package/apps/www/settings/profile/index.tsx +251 -248
  143. package/apps/www/settings/read-receipts/index.tsx +150 -147
  144. package/apps/www/settings/sharing/index.tsx +259 -256
  145. package/apps/www/settings/signatures/[uid].tsx +175 -172
  146. package/apps/www/settings/signatures/index.tsx +91 -88
  147. package/apps/www/settings/signatures/new/index.tsx +138 -135
  148. package/apps/www/tasks/index.tsx +654 -649
  149. package/dist/apps/admin/data-requests/index.js +1 -1
  150. package/dist/apps/admin/distribution-lists/new/index.js +3 -1
  151. package/dist/apps/admin/domains/[uid].js +3 -1
  152. package/dist/apps/admin/domains/new/index.js +3 -1
  153. package/dist/apps/admin/escrow-scopes/[uid].js +3 -1
  154. package/dist/apps/admin/escrow-scopes/new/index.js +3 -1
  155. package/dist/apps/admin/index.js +5 -2
  156. package/dist/apps/admin/mailboxes/[uid].js +15 -3
  157. package/dist/apps/admin/mailboxes/new/index.js +3 -1
  158. package/dist/apps/admin/transport-rules/new/index.js +3 -1
  159. package/dist/apps/escrow/matters/new/index.js +3 -1
  160. package/dist/apps/shared/components/admin/layout/AdminShell.js +6 -3
  161. package/dist/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.d.ts +35 -0
  162. package/dist/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.js +115 -0
  163. package/dist/apps/shared/components/admin/mailboxes/LeftoverMailboxesSection.d.ts +16 -0
  164. package/dist/apps/shared/components/admin/mailboxes/LeftoverMailboxesSection.js +92 -0
  165. package/dist/apps/shared/components/admin/settings/BrandingForm.js +3 -3
  166. package/dist/apps/shared/components/admin/settings/MailboxCreateForm.js +25 -3
  167. package/dist/apps/shared/components/admin/setup/SetupWizard.js +3 -1
  168. package/dist/apps/shared/components/calendar/EventEditor.js +5 -10
  169. package/dist/apps/shared/components/calendar/EventFormParts.d.ts +3 -2
  170. package/dist/apps/shared/components/calendar/EventFormParts.js +5 -16
  171. package/dist/apps/shared/components/calendar/GuestInput.d.ts +45 -0
  172. package/dist/apps/shared/components/calendar/GuestInput.js +30 -0
  173. package/dist/apps/shared/components/calendar/RequestChangeForm.js +11 -22
  174. package/dist/apps/shared/components/calendar/eventForm.d.ts +2 -2
  175. package/dist/apps/shared/components/calendar/eventFormat.d.ts +21 -8
  176. package/dist/apps/shared/components/calendar/eventFormat.js +50 -23
  177. package/dist/apps/shared/components/calendar/layout/CalendarShell.js +5 -4
  178. package/dist/apps/shared/components/contacts/ContactsSidebar.js +1 -1
  179. package/dist/apps/shared/components/contacts/ContactsToolbar.d.ts +3 -1
  180. package/dist/apps/shared/components/contacts/ContactsToolbar.js +4 -2
  181. package/dist/apps/shared/components/contacts/layout/ContactsShell.js +7 -5
  182. package/dist/apps/shared/components/layout/AppShell.d.ts +8 -11
  183. package/dist/apps/shared/components/layout/AppShell.js +24 -33
  184. package/dist/apps/shared/components/layout/FloatingActionButton.d.ts +13 -0
  185. package/dist/apps/shared/components/layout/FloatingActionButton.js +9 -0
  186. package/dist/apps/shared/components/layout/UserMenu.d.ts +4 -1
  187. package/dist/apps/shared/components/layout/UserMenu.js +6 -5
  188. package/dist/apps/shared/components/mail/ConversationThreadPane.js +127 -22
  189. package/dist/apps/shared/components/mail/EmptyFolderBar.d.ts +18 -0
  190. package/dist/apps/shared/components/mail/EmptyFolderBar.js +10 -0
  191. package/dist/apps/shared/components/mail/MailSelectionBar.d.ts +14 -4
  192. package/dist/apps/shared/components/mail/MailSelectionBar.js +11 -13
  193. package/dist/apps/shared/components/mail/MenuButton.d.ts +9 -2
  194. package/dist/apps/shared/components/mail/MenuButton.js +15 -11
  195. package/dist/apps/shared/components/mail/MessageDetailPane.d.ts +5 -0
  196. package/dist/apps/shared/components/mail/MessageDetailPane.js +147 -7
  197. package/dist/apps/shared/components/mail/PermanentDeleteDialog.d.ts +19 -0
  198. package/dist/apps/shared/components/mail/PermanentDeleteDialog.js +11 -0
  199. package/dist/apps/shared/components/mail/compose/ComposeWindow.js +8 -4
  200. package/dist/apps/shared/components/mail/compose/RecipientInput.d.ts +21 -1
  201. package/dist/apps/shared/components/mail/compose/RecipientInput.js +18 -10
  202. package/dist/apps/shared/components/mail/layout/FolderBadgeChip.d.ts +6 -0
  203. package/dist/apps/shared/components/mail/layout/FolderBadgeChip.js +9 -0
  204. package/dist/apps/shared/components/mail/layout/MailShell.d.ts +16 -7
  205. package/dist/apps/shared/components/mail/layout/MailShell.js +78 -65
  206. package/dist/apps/shared/components/mail/layout/SidebarSection.d.ts +23 -0
  207. package/dist/apps/shared/components/mail/layout/SidebarSection.js +16 -0
  208. package/dist/apps/shared/components/mail/reading/MessageMoreMenu.d.ts +56 -0
  209. package/dist/apps/shared/components/mail/reading/MessageMoreMenu.js +153 -0
  210. package/dist/apps/shared/components/mail/reading/MessageSourceDialog.d.ts +27 -0
  211. package/dist/apps/shared/components/mail/reading/MessageSourceDialog.js +27 -0
  212. package/dist/apps/shared/components/mail/reading/PendingMessageCard.d.ts +14 -0
  213. package/dist/apps/shared/components/mail/reading/PendingMessageCard.js +16 -0
  214. package/dist/apps/shared/components/mail/reading/messageExport.d.ts +19 -0
  215. package/dist/apps/shared/components/mail/reading/messageExport.js +51 -0
  216. package/dist/apps/shared/components/mail/reading/printMessage.d.ts +30 -0
  217. package/dist/apps/shared/components/mail/reading/printMessage.js +70 -0
  218. package/dist/apps/shared/components/mail/reading/useMessageActions.d.ts +57 -0
  219. package/dist/apps/shared/components/mail/reading/useMessageActions.js +366 -0
  220. package/dist/apps/shared/components/settings/layout/SettingsShell.js +10 -7
  221. package/dist/apps/shared/components/tasks/TasksSidebar.js +1 -1
  222. package/dist/apps/shared/components/tasks/layout/TasksShell.js +7 -5
  223. package/dist/apps/shared/keyboard/GlobalShortcuts.js +1 -1
  224. package/dist/apps/shared/mail/folderCounts.d.ts +10 -0
  225. package/dist/apps/shared/mail/folderCounts.js +12 -0
  226. package/dist/apps/shared/mail/folderOfType.d.ts +13 -0
  227. package/dist/apps/shared/mail/folderOfType.js +40 -0
  228. package/dist/apps/shared/mail/outbox/outgoingReplies.d.ts +80 -0
  229. package/dist/apps/shared/mail/outbox/outgoingReplies.js +131 -0
  230. package/dist/apps/shared/mail/outbox/sendJob.d.ts +5 -1
  231. package/dist/apps/shared/mail/outbox/sendJob.js +14 -1
  232. package/dist/apps/shared/mail/outbox/sendOutcomes.js +13 -4
  233. package/dist/apps/shared/mail/permanentDelete.d.ts +62 -0
  234. package/dist/apps/shared/mail/permanentDelete.js +127 -0
  235. package/dist/apps/shared/mail/primaryMailbox.d.ts +29 -0
  236. package/dist/apps/shared/mail/primaryMailbox.js +61 -0
  237. package/dist/apps/shared/mail/reportNotices.d.ts +21 -0
  238. package/dist/apps/shared/mail/reportNotices.js +47 -0
  239. package/dist/apps/shared/mail/senderBlocking.d.ts +26 -0
  240. package/dist/apps/shared/mail/senderBlocking.js +92 -0
  241. package/dist/apps/shared/mail/useCollapsedSections.d.ts +32 -0
  242. package/dist/apps/shared/mail/useCollapsedSections.js +110 -0
  243. package/dist/apps/shared/mail/useMailConnection.js +3 -1
  244. package/dist/apps/shared/mail/useMailboxUpdateAccess.d.ts +11 -0
  245. package/dist/apps/shared/mail/useMailboxUpdateAccess.js +52 -0
  246. package/dist/apps/shared/mail/usePermanentDelete.d.ts +35 -0
  247. package/dist/apps/shared/mail/usePermanentDelete.js +96 -0
  248. package/dist/apps/shared/navigation/frameContext.d.ts +1 -1
  249. package/dist/apps/shared/navigation/index.d.ts +16 -0
  250. package/dist/apps/shared/navigation/index.js +34 -0
  251. package/dist/apps/shared/navigation/pageTitle.d.ts +11 -0
  252. package/dist/apps/shared/navigation/pageTitle.js +12 -0
  253. package/dist/apps/shared/search/crossMailboxSearch.d.ts +72 -0
  254. package/dist/apps/shared/search/crossMailboxSearch.js +136 -0
  255. package/dist/apps/shared/styles/app.css +396 -386
  256. package/dist/apps/www/_shell.d.ts +26 -0
  257. package/dist/apps/www/_shell.js +31 -0
  258. package/dist/apps/www/calendar/index.d.ts +7 -2
  259. package/dist/apps/www/calendar/index.js +7 -4
  260. package/dist/apps/www/contacts/[uid].d.ts +14 -3
  261. package/dist/apps/www/contacts/[uid].js +5 -3
  262. package/dist/apps/www/contacts/index.d.ts +7 -2
  263. package/dist/apps/www/contacts/index.js +8 -4
  264. package/dist/apps/www/index.d.ts +7 -2
  265. package/dist/apps/www/index.js +542 -207
  266. package/dist/apps/www/messages/[uid].d.ts +14 -3
  267. package/dist/apps/www/messages/[uid].js +7 -5
  268. package/dist/apps/www/settings/appearance/index.d.ts +8 -2
  269. package/dist/apps/www/settings/appearance/index.js +4 -2
  270. package/dist/apps/www/settings/auto-reply/index.d.ts +7 -2
  271. package/dist/apps/www/settings/auto-reply/index.js +4 -2
  272. package/dist/apps/www/settings/blocked-senders/index.d.ts +9 -0
  273. package/dist/apps/www/settings/blocked-senders/index.js +134 -0
  274. package/dist/apps/www/settings/encryption/index.d.ts +7 -2
  275. package/dist/apps/www/settings/encryption/index.js +4 -2
  276. package/dist/apps/www/settings/filters/[uid].d.ts +7 -2
  277. package/dist/apps/www/settings/filters/[uid].js +4 -2
  278. package/dist/apps/www/settings/filters/index.d.ts +7 -2
  279. package/dist/apps/www/settings/filters/index.js +4 -2
  280. package/dist/apps/www/settings/filters/new/index.d.ts +7 -2
  281. package/dist/apps/www/settings/filters/new/index.js +28 -5
  282. package/dist/apps/www/settings/labels/index.d.ts +7 -2
  283. package/dist/apps/www/settings/labels/index.js +4 -2
  284. package/dist/apps/www/settings/privacy/index.d.ts +7 -2
  285. package/dist/apps/www/settings/privacy/index.js +4 -2
  286. package/dist/apps/www/settings/profile/index.d.ts +7 -2
  287. package/dist/apps/www/settings/profile/index.js +4 -2
  288. package/dist/apps/www/settings/read-receipts/index.d.ts +7 -2
  289. package/dist/apps/www/settings/read-receipts/index.js +4 -2
  290. package/dist/apps/www/settings/sharing/index.d.ts +7 -2
  291. package/dist/apps/www/settings/sharing/index.js +4 -2
  292. package/dist/apps/www/settings/signatures/[uid].d.ts +7 -2
  293. package/dist/apps/www/settings/signatures/[uid].js +4 -2
  294. package/dist/apps/www/settings/signatures/index.d.ts +7 -2
  295. package/dist/apps/www/settings/signatures/index.js +4 -2
  296. package/dist/apps/www/settings/signatures/new/index.d.ts +7 -2
  297. package/dist/apps/www/settings/signatures/new/index.js +5 -3
  298. package/dist/apps/www/tasks/index.d.ts +7 -2
  299. package/dist/apps/www/tasks/index.js +5 -3
  300. package/package.json +4 -2
  301. package/apps/shared/navigation/AppRouter.tsx +0 -300
  302. package/apps/shared/navigation/idle.ts +0 -45
  303. package/apps/shared/navigation/routerContext.tsx +0 -83
  304. package/apps/shared/navigation/routes.ts +0 -72
  305. package/apps/www/_routedPage.tsx +0 -24
  306. package/apps/www/_routes.ts +0 -37
  307. package/dist/apps/shared/navigation/AppRouter.d.ts +0 -52
  308. package/dist/apps/shared/navigation/AppRouter.js +0 -242
  309. package/dist/apps/shared/navigation/idle.d.ts +0 -14
  310. package/dist/apps/shared/navigation/idle.js +0 -43
  311. package/dist/apps/shared/navigation/routerContext.d.ts +0 -37
  312. package/dist/apps/shared/navigation/routerContext.js +0 -56
  313. package/dist/apps/shared/navigation/routes.d.ts +0 -32
  314. package/dist/apps/shared/navigation/routes.js +0 -37
  315. package/dist/apps/www/_routedPage.d.ts +0 -12
  316. package/dist/apps/www/_routedPage.js +0 -19
  317. package/dist/apps/www/_routes.d.ts +0 -11
  318. package/dist/apps/www/_routes.js +0 -31
@@ -1,206 +1,206 @@
1
- ///////////////////////////////////////////////////////////////////////////////
2
- // Copyright (C) 2026 Jean-Philippe Steinmetz
3
- // SPDX-License-Identifier: MPL-2.0
4
- ///////////////////////////////////////////////////////////////////////////////
5
- import React, { useRef, useState } from "react";
6
- import { Mailbox } from "@rapidmx/react-shared/mail/mailApi.js";
7
- import { CalendarOccurrence } from "@rapidmx/react-shared/calendar/recurrence.js";
8
- import Modal from "@rapidmx/react-shared/components/overlays/Modal.js";
9
- import Button from "@rapidmx/react-shared/components/buttons/Button.js";
10
- import useIsMobile from "@rapidmx/react-shared/util/useIsMobile.js";
11
- import EventDetails from "./EventDetails.js";
12
- import EventEditor from "./EventEditor.js";
13
- import EventShell, { EventAnchor, EventShellVariant } from "./EventShell.js";
14
- import { QuickTab } from "./QuickCreateTabs.js";
15
-
16
- export { VIDEO_LOCATION_PLACEHOLDER } from "./EventEditor.js";
17
- export type { EventAnchor } from "./EventShell.js";
18
-
19
- export interface EventModalProps {
20
- open: boolean;
21
- onClose: () => void;
22
- mailboxUid: string;
23
- /** The calendar folder a new event is created into (ignored when editing — an existing event keeps
24
- * its own `folderUid`). When `calendars` names more than one option, a "Calendar" selector lets the
25
- * user override this default before saving. */
26
- folderUid: string;
27
- /** Every calendar the caller could create this event into. Omitted, or a single entry, means "only
28
- * one calendar exists" — no selector is shown and `folderUid` is used as-is, matching this
29
- * component's original single-calendar behavior exactly. */
30
- calendars?: { uid: string; name: string }[];
31
- /** Every mailbox a new event could be created in, each with its own calendars. With more than one, a
32
- * "Mailbox" selector (create mode only) chooses the mailbox, which in turn drives the Calendar selector
33
- * and the organizer address; `mailboxUid`/`folderUid` are the initial selection. */
34
- mailboxOptions?: { mailbox: Mailbox; calendars: { uid: string; name: string }[] }[];
35
- /** Each calendar's colour, keyed by folder uid: the dot next to the calendar's name. */
36
- folderColors?: Record<string, string>;
37
- organizerAddress: string;
38
- /** The viewing mailbox's alias addresses - an event it organizes (or an invitation to it) may name any of
39
- * them instead of `organizerAddress`. Defaults to that mailbox's `aliasAddresses` from `mailboxOptions`. */
40
- organizerAliases?: string[];
41
- /** `null` when creating a new event. */
42
- occurrence: CalendarOccurrence | null;
43
- /** Prefilled start/end for create mode (e.g. the day/slot the user clicked). */
44
- initialStart?: Date;
45
- initialEnd?: Date;
46
- /** Create mode: start as an all-day event on `initialStart`'s day (a day of the month view was clicked). */
47
- initialAllDay?: boolean;
48
- /** Create mode: what was clicked (a slot, a day, the New event button), which the quick-create popover opens beside. Without one it
49
- * opens centered near the top of the window. */
50
- anchor?: EventAnchor;
51
- /** Where the booking plugin's Settings pages are (`/settings/booking-types`) when it is running: a new event then has an Appointment
52
- * schedule tab, and its More options opens the plugin's own new-link page. Without it there are only the Event and Task tabs. */
53
- bookingHref?: string;
54
- onSaved: () => void;
55
- onDeleted: () => void;
56
- }
57
-
58
- /** How wide each face of the dialog gets, in px. */
59
- const QUICK_WIDTH = 450;
60
- const DETAILS_WIDTH = 480;
61
- const FORM_WIDTH = 880;
62
- const TASK_FORM_WIDTH = 560;
63
-
64
- /**
65
- * The calendar's event dialog, in three faces drawn through one frame (`EventShell`):
66
- *
67
- * - **A new event** opens as a quick-create popover (`EventQuickForm`, beside what was clicked; a bottom sheet on a phone). "More options"
68
- * grows it into the full card (`EventExpandedForm`) with everything typed so far still in it.
69
- * The popover has tabs (`QuickCreateTabs`): Event, Task, and - when the booking plugin is running (`bookingHref`) - Appointment schedule.
70
- * The Task and Appointment faces are drawn by `QuickCreateFaces`, share the Event tab's title, mailbox and calendar, and only ever
71
- * create a task or a booking type; the Event tab is the form it always was.
72
- * - **An existing event** opens read-only (`EventDetails`): what the event says, the invited reader's Accept / Tentative / Decline,
73
- * and Delete. The reader who organized it also gets Modify, which turns the same card into the full form; closing that form returns
74
- * to the details, discarding the edits (a save closes everything, as it always did).
75
- *
76
- * Editing or deleting a recurring event's occurrence offers a choice between "this event" and "the entire series" (see
77
- * `calendarMutations.ts`) — Outlook's own convention for the same ambiguity.
78
- */
79
- export default function EventModal({
80
- open,
81
- onClose,
82
- mailboxUid,
83
- folderUid,
84
- calendars,
85
- mailboxOptions,
86
- folderColors,
87
- organizerAddress,
88
- organizerAliases,
89
- occurrence,
90
- initialStart,
91
- initialEnd,
92
- initialAllDay,
93
- anchor,
94
- bookingHref,
95
- onSaved,
96
- onDeleted,
97
- }: EventModalProps) {
98
- const isMobile = useIsMobile();
99
- // An existing event: Modify was pressed. A new event: More options was.
100
- const [editing, setEditing] = useState(false);
101
- const [expanded, setExpanded] = useState(false);
102
- // A new event: what the popover creates (an event, a task or an appointment schedule). More options only ever grows the tab it was pressed on.
103
- const [tab, setTab] = useState<QuickTab>("event");
104
- const [syncWarning, setSyncWarning] = useState(false);
105
- // Whether the form holds anything a click on the backdrop would throw away (kept up to date by the editor).
106
- const dirtyRef = useRef(false);
107
-
108
- if (!open) {
109
- return null;
110
- }
111
-
112
- if (syncWarning) {
113
- return (
114
- <Modal open={open} onClose={onSaved} title="Series saved">
115
- <p role="alert" className="text-sm mb-4">
116
- The series was saved, but some occurrences you had changed individually couldn&rsquo;t be moved with it. They
117
- may now appear twice - check the calendar and delete any duplicate.
118
- </p>
119
- <Button type="button" className="!w-auto" onClick={onSaved}>
120
- OK
121
- </Button>
122
- </Modal>
123
- );
124
- }
125
-
126
- // Every address the viewing mailbox receives at - its primary address and its aliases, case-insensitively.
127
- const ownAddresses = new Set(
128
- [organizerAddress, ...(organizerAliases ?? mailboxOptions?.find((option) => option.mailbox.uid === mailboxUid)?.mailbox.aliasAddresses ?? [])].map(
129
- (address) => address.toLowerCase(),
130
- ),
131
- );
132
- const isOwnAddress = (address: string) => ownAddresses.has(address.toLowerCase());
133
- // An existing event organized by someone else is the viewing mailbox's copy of an invitation: only the
134
- // organizer can change it (their next update would overwrite local edits anyway), so it can't be modified.
135
- const isInvited =
136
- !!occurrence && !isOwnAddress(occurrence.organizer.address) && !occurrence.attendees.some((a) => a.isOrganizer && isOwnAddress(a.address));
137
- // The viewing mailbox can respond to an *existing* event it's invited to but doesn't organize - finding one of its own
138
- // addresses among the attendees (and not as that attendee's own organizer flag) identifies exactly that case.
139
- const myAttendee = occurrence?.attendees.find((a) => isOwnAddress(a.address));
140
- const canRespond = !!myAttendee && !myAttendee.isOrganizer;
141
-
142
- const isForm = !occurrence || editing;
143
- const layout = occurrence || expanded ? "expanded" : "quick";
144
- const variant: EventShellVariant = !isForm || layout === "expanded" ? "card" : isMobile ? "sheet" : "popover";
145
- const width = !isForm ? DETAILS_WIDTH : layout === "expanded" ? (tab === "event" || occurrence ? FORM_WIDTH : TASK_FORM_WIDTH) : QUICK_WIDTH;
146
- // Leaving the form: an existing event goes back to its details, a new one is done.
147
- const leaveForm = occurrence ? () => setEditing(false) : onClose;
148
-
149
- return (
150
- <EventShell
151
- variant={variant}
152
- label={!occurrence ? "New event" : editing ? "Edit event" : "Event details"}
153
- focusKey={isForm ? layout : "details"}
154
- anchor={anchor}
155
- width={width}
156
- onClose={isForm ? leaveForm : onClose}
157
- onBackdropPress={isForm ? () => !dirtyRef.current && leaveForm() : undefined}
158
- >
159
- {isForm ? (
160
- <EventEditor
161
- layout={layout}
162
- onExpand={() => setExpanded(true)}
163
- onCancel={leaveForm}
164
- onSaved={onSaved}
165
- onSyncWarning={() => setSyncWarning(true)}
166
- dirtyRef={dirtyRef}
167
- mailboxUid={mailboxUid}
168
- folderUid={folderUid}
169
- calendars={calendars}
170
- mailboxOptions={mailboxOptions}
171
- folderColors={folderColors}
172
- organizerAddress={organizerAddress}
173
- occurrence={occurrence}
174
- initialStart={initialStart}
175
- initialEnd={initialEnd}
176
- initialAllDay={initialAllDay}
177
- quickCreate={
178
- occurrence
179
- ? undefined
180
- : {
181
- tab,
182
- onTabChange: (next) => {
183
- setTab(next);
184
- setExpanded(false);
185
- },
186
- bookingHref,
187
- }
188
- }
189
- />
190
- ) : (
191
- <EventDetails
192
- occurrence={occurrence}
193
- isInvited={isInvited}
194
- myResponse={canRespond ? myAttendee.responseStatus : undefined}
195
- isOwnAddress={isOwnAddress}
196
- calendarName={calendars?.find((cal) => cal.uid === occurrence.folderUid)?.name}
197
- calendarColor={folderColors?.[occurrence.folderUid]}
198
- onClose={onClose}
199
- onModify={() => setEditing(true)}
200
- onSaved={onSaved}
201
- onDeleted={onDeleted}
202
- />
203
- )}
204
- </EventShell>
205
- );
206
- }
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+ import React, { useRef, useState } from "react";
6
+ import { Mailbox } from "@rapidmx/react-shared/mail/mailApi.js";
7
+ import { CalendarOccurrence } from "@rapidmx/react-shared/calendar/recurrence.js";
8
+ import Modal from "@rapidmx/react-shared/components/overlays/Modal.js";
9
+ import Button from "@rapidmx/react-shared/components/buttons/Button.js";
10
+ import useIsMobile from "@rapidmx/react-shared/util/useIsMobile.js";
11
+ import EventDetails from "./EventDetails.js";
12
+ import EventEditor from "./EventEditor.js";
13
+ import EventShell, { EventAnchor, EventShellVariant } from "./EventShell.js";
14
+ import { QuickTab } from "./QuickCreateTabs.js";
15
+
16
+ export { VIDEO_LOCATION_PLACEHOLDER } from "./EventEditor.js";
17
+ export type { EventAnchor } from "./EventShell.js";
18
+
19
+ export interface EventModalProps {
20
+ open: boolean;
21
+ onClose: () => void;
22
+ mailboxUid: string;
23
+ /** The calendar folder a new event is created into (ignored when editing — an existing event keeps
24
+ * its own `folderUid`). When `calendars` names more than one option, a "Calendar" selector lets the
25
+ * user override this default before saving. */
26
+ folderUid: string;
27
+ /** Every calendar the caller could create this event into. Omitted, or a single entry, means "only
28
+ * one calendar exists" — no selector is shown and `folderUid` is used as-is, matching this
29
+ * component's original single-calendar behavior exactly. */
30
+ calendars?: { uid: string; name: string }[];
31
+ /** Every mailbox a new event could be created in, each with its own calendars. With more than one, a
32
+ * "Mailbox" selector (create mode only) chooses the mailbox, which in turn drives the Calendar selector
33
+ * and the organizer address; `mailboxUid`/`folderUid` are the initial selection. */
34
+ mailboxOptions?: { mailbox: Mailbox; calendars: { uid: string; name: string }[] }[];
35
+ /** Each calendar's colour, keyed by folder uid: the dot next to the calendar's name. */
36
+ folderColors?: Record<string, string>;
37
+ organizerAddress: string;
38
+ /** The viewing mailbox's alias addresses - an event it organizes (or an invitation to it) may name any of
39
+ * them instead of `organizerAddress`. Defaults to that mailbox's `aliasAddresses` from `mailboxOptions`. */
40
+ organizerAliases?: string[];
41
+ /** `null` when creating a new event. */
42
+ occurrence: CalendarOccurrence | null;
43
+ /** Prefilled start/end for create mode (e.g. the day/slot the user clicked). */
44
+ initialStart?: Date;
45
+ initialEnd?: Date;
46
+ /** Create mode: start as an all-day event on `initialStart`'s day (a day of the month view was clicked). */
47
+ initialAllDay?: boolean;
48
+ /** Create mode: what was clicked (a slot, a day, the New event button), which the quick-create popover opens beside. Without one it
49
+ * opens centered near the top of the window. */
50
+ anchor?: EventAnchor;
51
+ /** Where the booking plugin's Settings pages are (`/settings/booking-types`) when it is running: a new event then has an Appointment
52
+ * schedule tab, and its More options opens the plugin's own new-link page. Without it there are only the Event and Task tabs. */
53
+ bookingHref?: string;
54
+ onSaved: () => void;
55
+ onDeleted: () => void;
56
+ }
57
+
58
+ /** How wide each face of the dialog gets, in px. */
59
+ const QUICK_WIDTH = 450;
60
+ const DETAILS_WIDTH = 480;
61
+ const FORM_WIDTH = 880;
62
+ const TASK_FORM_WIDTH = 560;
63
+
64
+ /**
65
+ * The calendar's event dialog, in three faces drawn through one frame (`EventShell`):
66
+ *
67
+ * - **A new event** opens as a quick-create popover (`EventQuickForm`, beside what was clicked; a bottom sheet on a phone). "More options"
68
+ * grows it into the full card (`EventExpandedForm`) with everything typed so far still in it.
69
+ * The popover has tabs (`QuickCreateTabs`): Event, Task, and - when the booking plugin is running (`bookingHref`) - Appointment schedule.
70
+ * The Task and Appointment faces are drawn by `QuickCreateFaces`, share the Event tab's title, mailbox and calendar, and only ever
71
+ * create a task or a booking type; the Event tab is the form it always was.
72
+ * - **An existing event** opens read-only (`EventDetails`): what the event says, the invited reader's Accept / Tentative / Decline,
73
+ * and Delete. The reader who organized it also gets Modify, which turns the same card into the full form; closing that form returns
74
+ * to the details, discarding the edits (a save closes everything, as it always did).
75
+ *
76
+ * Editing or deleting a recurring event's occurrence offers a choice between "this event" and "the entire series" (see
77
+ * `calendarMutations.ts`) — Outlook's own convention for the same ambiguity.
78
+ */
79
+ export default function EventModal({
80
+ open,
81
+ onClose,
82
+ mailboxUid,
83
+ folderUid,
84
+ calendars,
85
+ mailboxOptions,
86
+ folderColors,
87
+ organizerAddress,
88
+ organizerAliases,
89
+ occurrence,
90
+ initialStart,
91
+ initialEnd,
92
+ initialAllDay,
93
+ anchor,
94
+ bookingHref,
95
+ onSaved,
96
+ onDeleted,
97
+ }: EventModalProps) {
98
+ const isMobile = useIsMobile();
99
+ // An existing event: Modify was pressed. A new event: More options was.
100
+ const [editing, setEditing] = useState(false);
101
+ const [expanded, setExpanded] = useState(false);
102
+ // A new event: what the popover creates (an event, a task or an appointment schedule). More options only ever grows the tab it was pressed on.
103
+ const [tab, setTab] = useState<QuickTab>("event");
104
+ const [syncWarning, setSyncWarning] = useState(false);
105
+ // Whether the form holds anything a click on the backdrop would throw away (kept up to date by the editor).
106
+ const dirtyRef = useRef(false);
107
+
108
+ if (!open) {
109
+ return null;
110
+ }
111
+
112
+ if (syncWarning) {
113
+ return (
114
+ <Modal open={open} onClose={onSaved} title="Series saved">
115
+ <p role="alert" className="text-sm mb-4">
116
+ The series was saved, but some occurrences you had changed individually couldn&rsquo;t be moved with it. They
117
+ may now appear twice - check the calendar and delete any duplicate.
118
+ </p>
119
+ <Button type="button" className="!w-auto" onClick={onSaved}>
120
+ OK
121
+ </Button>
122
+ </Modal>
123
+ );
124
+ }
125
+
126
+ // Every address the viewing mailbox receives at - its primary address and its aliases, case-insensitively.
127
+ const ownAddresses = new Set(
128
+ [organizerAddress, ...(organizerAliases ?? mailboxOptions?.find((option) => option.mailbox.uid === mailboxUid)?.mailbox.aliasAddresses ?? [])].map(
129
+ (address) => address.toLowerCase(),
130
+ ),
131
+ );
132
+ const isOwnAddress = (address: string) => ownAddresses.has(address.toLowerCase());
133
+ // An existing event organized by someone else is the viewing mailbox's copy of an invitation: only the
134
+ // organizer can change it (their next update would overwrite local edits anyway), so it can't be modified.
135
+ const isInvited =
136
+ !!occurrence && !isOwnAddress(occurrence.organizer.address) && !occurrence.attendees.some((a) => a.isOrganizer && isOwnAddress(a.address));
137
+ // The viewing mailbox can respond to an *existing* event it's invited to but doesn't organize - finding one of its own
138
+ // addresses among the attendees (and not as that attendee's own organizer flag) identifies exactly that case.
139
+ const myAttendee = occurrence?.attendees.find((a) => isOwnAddress(a.address));
140
+ const canRespond = !!myAttendee && !myAttendee.isOrganizer;
141
+
142
+ const isForm = !occurrence || editing;
143
+ const layout = occurrence || expanded ? "expanded" : "quick";
144
+ const variant: EventShellVariant = !isForm || layout === "expanded" ? "card" : isMobile ? "sheet" : "popover";
145
+ const width = !isForm ? DETAILS_WIDTH : layout === "expanded" ? (tab === "event" || occurrence ? FORM_WIDTH : TASK_FORM_WIDTH) : QUICK_WIDTH;
146
+ // Leaving the form: an existing event goes back to its details, a new one is done.
147
+ const leaveForm = occurrence ? () => setEditing(false) : onClose;
148
+
149
+ return (
150
+ <EventShell
151
+ variant={variant}
152
+ label={!occurrence ? "New event" : editing ? "Edit event" : "Event details"}
153
+ focusKey={isForm ? layout : "details"}
154
+ anchor={anchor}
155
+ width={width}
156
+ onClose={isForm ? leaveForm : onClose}
157
+ onBackdropPress={isForm ? () => !dirtyRef.current && leaveForm() : undefined}
158
+ >
159
+ {isForm ? (
160
+ <EventEditor
161
+ layout={layout}
162
+ onExpand={() => setExpanded(true)}
163
+ onCancel={leaveForm}
164
+ onSaved={onSaved}
165
+ onSyncWarning={() => setSyncWarning(true)}
166
+ dirtyRef={dirtyRef}
167
+ mailboxUid={mailboxUid}
168
+ folderUid={folderUid}
169
+ calendars={calendars}
170
+ mailboxOptions={mailboxOptions}
171
+ folderColors={folderColors}
172
+ organizerAddress={organizerAddress}
173
+ occurrence={occurrence}
174
+ initialStart={initialStart}
175
+ initialEnd={initialEnd}
176
+ initialAllDay={initialAllDay}
177
+ quickCreate={
178
+ occurrence
179
+ ? undefined
180
+ : {
181
+ tab,
182
+ onTabChange: (next) => {
183
+ setTab(next);
184
+ setExpanded(false);
185
+ },
186
+ bookingHref,
187
+ }
188
+ }
189
+ />
190
+ ) : (
191
+ <EventDetails
192
+ occurrence={occurrence}
193
+ isInvited={isInvited}
194
+ myResponse={canRespond ? myAttendee.responseStatus : undefined}
195
+ isOwnAddress={isOwnAddress}
196
+ calendarName={calendars?.find((cal) => cal.uid === occurrence.folderUid)?.name}
197
+ calendarColor={folderColors?.[occurrence.folderUid]}
198
+ onClose={onClose}
199
+ onModify={() => setEditing(true)}
200
+ onSaved={onSaved}
201
+ onDeleted={onDeleted}
202
+ />
203
+ )}
204
+ </EventShell>
205
+ );
206
+ }
@@ -0,0 +1,100 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+ import React from "react";
6
+ import type { Attendee } from "@rapidmx/react-shared/calendar/calendarApi.js";
7
+ import type { ContactSuggestionOptions, RecipientSuggestion } from "@rapidmx/react-shared/mail/directoryApi.js";
8
+ import RecipientInput from "../mail/compose/RecipientInput.js";
9
+ import { applyGuestChips, guestChip } from "./eventFormat.js";
10
+
11
+ /** Above the event dialog's own backdrop (`z-[1000]`), which the suggestions would otherwise sit under. */
12
+ const DIALOG_SUGGESTIONS_Z_INDEX = 1100;
13
+
14
+ const VARIANT_CLASS = {
15
+ /** Reads as plain text until it is hovered or focused, as the rows of the quick-create popover do. */
16
+ quiet: "w-full text-sm py-1 border-b border-transparent hover:border-border focus-within:border-primary",
17
+ /** A bordered box, as the full form's fields are. */
18
+ box: "w-full text-sm py-1.5 px-3 border border-border rounded-md bg-surface text-text focus-within:border-primary",
19
+ };
20
+
21
+ /** What a guests field holds: the guests added, what was committed but is not an address (kept in the field, flagged, until it is fixed or removed),
22
+ * and what is still being typed. */
23
+ export interface GuestEntries {
24
+ guests: Attendee[];
25
+ invalid: string[];
26
+ draft: string;
27
+ }
28
+
29
+ export interface GuestInputProps extends GuestEntries {
30
+ /** The input's id, and the prefix of its suggestions' ids. */
31
+ id: string;
32
+ /** The input's accessible name. */
33
+ label: string;
34
+ placeholder?: string;
35
+ variant: keyof typeof VARIANT_CLASS;
36
+ /** The guests are listed elsewhere (rows with a role and an answer): the field draws chips only for what is not an address. */
37
+ listedElsewhere?: boolean;
38
+ /** Addresses that are never added - the organizer's, or the people already invited. */
39
+ skipAddresses?: string[];
40
+ /** The mailbox the event is on, whose contacts are suggested too. */
41
+ mailboxUid?: string;
42
+ onChange: (next: GuestEntries) => void;
43
+ /** Loads suggestions; defaults to the lookup compose's recipient fields use. */
44
+ fetchSuggestions?: (query: string, options: ContactSuggestionOptions) => Promise<RecipientSuggestion[]>;
45
+ debounceMs?: number;
46
+ }
47
+
48
+ /** What `RecipientInput` calls `onChange` with; the entries come through `onEdit`. */
49
+ const IGNORED = () => undefined;
50
+
51
+ /**
52
+ * The guests field of an event: compose's recipient field (`RecipientInput`) reading its chips as guests. Typing looks the name up among the
53
+ * caller's contacts and the server's mailboxes and distribution lists; a suggestion (or an address, `Name <address>`, a comma, a semicolon,
54
+ * Enter or leaving the field) becomes a chip, a paste of several addresses becomes several, and something that is not an address stays as
55
+ * a flagged chip once it is committed - nothing is said while it is being typed. A distribution list is added as its own address, one guest
56
+ * (as compose sends to one), which the mail server delivers to its members.
57
+ *
58
+ * The field is controlled: `guests` are the attendees, and every edit hands back the whole of the entries (see `applyGuestChips()`).
59
+ */
60
+ export default function GuestInput({
61
+ id,
62
+ label,
63
+ placeholder,
64
+ variant,
65
+ listedElsewhere,
66
+ skipAddresses,
67
+ mailboxUid,
68
+ guests,
69
+ invalid,
70
+ draft,
71
+ onChange,
72
+ fetchSuggestions,
73
+ debounceMs,
74
+ }: GuestInputProps) {
75
+ const value = [...guests.map(guestChip), ...invalid, draft].filter((part) => part.length > 0).join(", ");
76
+ const listed = new Set(listedElsewhere ? guests.map(guestChip) : []);
77
+
78
+ return (
79
+ <RecipientInput
80
+ id={id}
81
+ label={label}
82
+ ariaLabel={label}
83
+ listLabel="Guests"
84
+ placeholder={placeholder}
85
+ className={VARIANT_CLASS[variant]}
86
+ dropdownZIndex={DIALOG_SUGGESTIONS_Z_INDEX}
87
+ value={value}
88
+ initialPending={draft}
89
+ mailboxUid={mailboxUid}
90
+ hideChip={(chip) => listed.has(chip)}
91
+ fetchSuggestions={fetchSuggestions}
92
+ debounceMs={debounceMs}
93
+ onChange={IGNORED}
94
+ onEdit={(chips, pending) => {
95
+ const merged = applyGuestChips(guests, chips, skipAddresses);
96
+ onChange({ guests: merged.attendees, invalid: merged.invalid, draft: pending });
97
+ }}
98
+ />
99
+ );
100
+ }