@rapidmx/web-client 0.20.0 → 0.22.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 (906) hide show
  1. package/README.md +415 -381
  2. package/apps/admin/_layout.tsx +2 -2
  3. package/apps/admin/audit-log/index.tsx +4 -4
  4. package/apps/admin/branding/index.tsx +39 -39
  5. package/apps/admin/data-requests/index.tsx +482 -482
  6. package/apps/admin/distribution-lists/[uid].tsx +3 -3
  7. package/apps/admin/distribution-lists/index.tsx +4 -4
  8. package/apps/admin/distribution-lists/new/index.tsx +5 -5
  9. package/apps/admin/domains/[uid].tsx +166 -166
  10. package/apps/admin/domains/index.tsx +4 -4
  11. package/apps/admin/domains/new/index.tsx +5 -5
  12. package/apps/admin/encryption-policy/index.tsx +1 -1
  13. package/apps/admin/escrow-scopes/[uid].tsx +350 -350
  14. package/apps/admin/escrow-scopes/index.tsx +4 -4
  15. package/apps/admin/escrow-scopes/new/index.tsx +5 -5
  16. package/apps/admin/index.tsx +129 -129
  17. package/apps/admin/ingest-queue/index.tsx +4 -4
  18. package/apps/admin/mailbox-policy/index.tsx +1 -1
  19. package/apps/admin/mailboxes/[uid].tsx +271 -271
  20. package/apps/admin/mailboxes/new/index.tsx +30 -30
  21. package/apps/admin/plugins/index.tsx +15 -15
  22. package/apps/admin/quarantine/index.tsx +5 -5
  23. package/apps/admin/retention-policy/index.tsx +39 -39
  24. package/apps/admin/signing-certificates/index.tsx +343 -343
  25. package/apps/admin/transport-rules/[uid].tsx +5 -5
  26. package/apps/admin/transport-rules/_transportRuleConfig.tsx +3 -3
  27. package/apps/admin/transport-rules/index.tsx +4 -4
  28. package/apps/admin/transport-rules/new/index.tsx +5 -5
  29. package/apps/escrow/_layout.tsx +1 -1
  30. package/apps/escrow/audit-log/index.tsx +196 -196
  31. package/apps/escrow/index.tsx +4 -4
  32. package/apps/escrow/matters/[uid].tsx +621 -621
  33. package/apps/escrow/matters/new/index.tsx +6 -6
  34. package/apps/shared/appearance/AppearanceForm.tsx +3 -3
  35. package/apps/shared/appearance/AppearanceHead.tsx +1 -1
  36. package/apps/shared/appearance/AppearanceProvider.tsx +3 -3
  37. package/apps/shared/appearance/appearanceCache.ts +1 -1
  38. package/apps/shared/appearance/appearanceContext.ts +1 -1
  39. package/apps/shared/appearance/theme.ts +1 -1
  40. package/apps/shared/auth/adminAccess.ts +99 -99
  41. package/apps/shared/calendar/bookingPlugin.ts +1 -1
  42. package/apps/shared/calendar/calendarLiveUpdates.ts +1 -1
  43. package/apps/shared/calendar/calendarReminders.ts +1 -1
  44. package/apps/shared/calendar/useCalendarReminders.ts +1 -1
  45. package/apps/shared/components/admin/diagnostics/DiagnosticsManager.tsx +1 -1
  46. package/apps/shared/components/admin/diagnostics/InstalledPlugins.tsx +2 -2
  47. package/apps/shared/components/admin/diagnostics/LogsPanel.tsx +2 -2
  48. package/apps/shared/components/admin/diagnostics/PackagesTable.tsx +1 -1
  49. package/apps/shared/components/admin/diagnostics/RuntimePanel.tsx +1 -1
  50. package/apps/shared/components/admin/diagnostics/SystemPanel.tsx +2 -2
  51. package/apps/shared/components/admin/diagnostics/VersionsPanel.tsx +1 -1
  52. package/apps/shared/components/admin/diagnostics/diagnosticsApi.ts +1 -1
  53. package/apps/shared/components/admin/diagnostics/format.ts +1 -1
  54. package/apps/shared/components/admin/diagnostics/logClient.ts +1 -1
  55. package/apps/shared/components/admin/distributionLists/MemberListCard.tsx +4 -4
  56. package/apps/shared/components/admin/elevation.ts +1 -1
  57. package/apps/shared/components/admin/escrowScopes/EscrowScopeKeyAndHoldersFields.tsx +3 -3
  58. package/apps/shared/components/admin/layout/AdminShell.tsx +384 -384
  59. package/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.tsx +238 -238
  60. package/apps/shared/components/admin/mailboxes/EscrowScopeCard.tsx +154 -152
  61. package/apps/shared/components/admin/mailboxes/LeftoverMailboxesSection.tsx +194 -194
  62. package/apps/shared/components/admin/mailboxes/MailboxTable.tsx +1 -1
  63. package/apps/shared/components/admin/mailboxes/ResourceSettingsCard.tsx +19 -14
  64. package/apps/shared/components/admin/mailboxes/ShareAccessCard.tsx +5 -5
  65. package/apps/shared/components/admin/settings/BrandingForm.tsx +423 -423
  66. package/apps/shared/components/admin/settings/DomainDnsSetup.tsx +5 -5
  67. package/apps/shared/components/admin/settings/EncryptionPolicyForm.tsx +119 -119
  68. package/apps/shared/components/admin/settings/LoadedSettingsForm.tsx +2 -2
  69. package/apps/shared/components/admin/settings/MailboxCreateForm.tsx +32 -27
  70. package/apps/shared/components/admin/settings/MailboxPolicyForm.tsx +198 -198
  71. package/apps/shared/components/admin/settings/PluginsManager.tsx +2093 -2093
  72. package/apps/shared/components/admin/settings/RetentionPolicyForm.tsx +182 -182
  73. package/apps/shared/components/admin/setup/EscrowSetupStep.tsx +288 -288
  74. package/apps/shared/components/admin/setup/SetupWizard.tsx +450 -446
  75. package/apps/shared/components/admin/signOut.ts +1 -1
  76. package/apps/shared/components/admin/usePagedList.tsx +129 -129
  77. package/apps/shared/components/calendar/AppointmentQuickForm.tsx +3 -3
  78. package/apps/shared/components/calendar/CalendarListSidebar.tsx +3 -3
  79. package/apps/shared/components/calendar/DescriptionEditor.tsx +1 -1
  80. package/apps/shared/components/calendar/EventDescriptionView.tsx +1 -1
  81. package/apps/shared/components/calendar/EventDetails.tsx +16 -14
  82. package/apps/shared/components/calendar/EventEditor.tsx +54 -39
  83. package/apps/shared/components/calendar/EventExpandedForm.tsx +3 -3
  84. package/apps/shared/components/calendar/EventFormParts.tsx +2 -2
  85. package/apps/shared/components/calendar/EventModal.tsx +206 -206
  86. package/apps/shared/components/calendar/EventQuickForm.tsx +3 -3
  87. package/apps/shared/components/calendar/EventShell.tsx +1 -1
  88. package/apps/shared/components/calendar/FindATime.tsx +6 -4
  89. package/apps/shared/components/calendar/GuestInput.tsx +2 -2
  90. package/apps/shared/components/calendar/MonthView.tsx +185 -185
  91. package/apps/shared/components/calendar/QuickCreateFaces.tsx +1 -1
  92. package/apps/shared/components/calendar/QuickFaceFrame.tsx +1 -1
  93. package/apps/shared/components/calendar/RecurrenceEditor.tsx +227 -227
  94. package/apps/shared/components/calendar/RequestChangeForm.tsx +8 -6
  95. package/apps/shared/components/calendar/ResourcePicker.tsx +7 -5
  96. package/apps/shared/components/calendar/SplitDayView.tsx +144 -144
  97. package/apps/shared/components/calendar/TaskQuickForm.tsx +23 -18
  98. package/apps/shared/components/calendar/TimeGridView.tsx +246 -246
  99. package/apps/shared/components/calendar/allDay.ts +124 -124
  100. package/apps/shared/components/calendar/eventDialogFields.ts +3 -3
  101. package/apps/shared/components/calendar/eventForm.ts +3 -3
  102. package/apps/shared/components/calendar/eventFormat.ts +3 -3
  103. package/apps/shared/components/calendar/findTimeGrid.ts +2 -2
  104. package/apps/shared/components/calendar/layout/CalendarShell.tsx +11 -9
  105. package/apps/shared/components/contacts/ContactDetailPane.tsx +4 -4
  106. package/apps/shared/components/contacts/ContactForm.tsx +393 -383
  107. package/apps/shared/components/contacts/ContactsSidebar.tsx +7 -5
  108. package/apps/shared/components/contacts/ContactsToolbar.tsx +103 -103
  109. package/apps/shared/components/contacts/KeyChangeReview.tsx +5 -5
  110. package/apps/shared/components/contacts/contactKeys.ts +3 -3
  111. package/apps/shared/components/contacts/layout/ContactsShell.tsx +9 -7
  112. package/apps/shared/components/escrow/layout/EscrowShell.tsx +155 -155
  113. package/apps/shared/components/forms/StringListField.tsx +1 -1
  114. package/apps/shared/components/layout/AppShell.tsx +465 -461
  115. package/apps/shared/components/layout/BrandingChrome.tsx +1 -1
  116. package/apps/shared/components/layout/KeyEnrollmentGate.tsx +398 -398
  117. package/apps/shared/components/layout/MailboxProvisioning.tsx +170 -168
  118. package/apps/shared/components/layout/RecoveryCodeUnlock.tsx +9 -9
  119. package/apps/shared/components/layout/ResponsiveToolbar.tsx +315 -315
  120. package/apps/shared/components/layout/ThemeSwitch.tsx +84 -84
  121. package/apps/shared/components/layout/UnlockPromptProvider.tsx +6 -6
  122. package/apps/shared/components/layout/UserMenu.tsx +441 -439
  123. package/apps/shared/components/mail/ConversationList.tsx +334 -332
  124. package/apps/shared/components/mail/ConversationThreadPane.tsx +624 -613
  125. package/apps/shared/components/mail/InviteCard.tsx +11 -9
  126. package/apps/shared/components/mail/LazyReadingPane.tsx +2 -2
  127. package/apps/shared/components/mail/MailAddress.tsx +1 -1
  128. package/apps/shared/components/mail/MailListToolbar.tsx +2 -2
  129. package/apps/shared/components/mail/MailSelectionBar.tsx +240 -240
  130. package/apps/shared/components/mail/MenuButton.tsx +404 -404
  131. package/apps/shared/components/mail/MessageDetailPane.tsx +1759 -1757
  132. package/apps/shared/components/mail/MoveToFolderDialog.tsx +8 -6
  133. package/apps/shared/components/mail/OutboxRowStatus.tsx +1 -1
  134. package/apps/shared/components/mail/PermanentDeleteDialog.tsx +2 -2
  135. package/apps/shared/components/mail/compose/ComposeContext.tsx +323 -312
  136. package/apps/shared/components/mail/compose/ComposeToolbar.tsx +422 -422
  137. package/apps/shared/components/mail/compose/ComposeWindow.tsx +1709 -1681
  138. package/apps/shared/components/mail/compose/ComposeWindowPlaceholder.tsx +4 -4
  139. package/apps/shared/components/mail/compose/EmojiPicker.tsx +2 -2
  140. package/apps/shared/components/mail/compose/GifPicker.tsx +3 -3
  141. package/apps/shared/components/mail/compose/RecipientInput.tsx +1 -1
  142. package/apps/shared/components/mail/compose/RichTextEditor.tsx +147 -147
  143. package/apps/shared/components/mail/compose/ScheduleSendPicker.tsx +1 -1
  144. package/apps/shared/components/mail/compose/composeFlushRegistry.ts +60 -60
  145. package/apps/shared/components/mail/compose/encryptionRequirement.ts +2 -2
  146. package/apps/shared/components/mail/compose/quotedBody.ts +161 -161
  147. package/apps/shared/components/mail/compose/recipients.ts +1 -1
  148. package/apps/shared/components/mail/invite/InviteRowChip.tsx +2 -2
  149. package/apps/shared/components/mail/invite/InviteRsvpPopover.tsx +9 -7
  150. package/apps/shared/components/mail/invite/InviteTimeline.tsx +1 -1
  151. package/apps/shared/components/mail/invite/ProposeTimeForm.tsx +2 -2
  152. package/apps/shared/components/mail/invite/inviteFormat.ts +2 -2
  153. package/apps/shared/components/mail/invite/inviteStore.ts +14 -6
  154. package/apps/shared/components/mail/labelMenu.tsx +9 -7
  155. package/apps/shared/components/mail/layout/MailShell.tsx +4 -4
  156. package/apps/shared/components/mail/listPreferences.ts +2 -2
  157. package/apps/shared/components/mail/pinnedSigners.ts +45 -19
  158. package/apps/shared/components/mail/reading/EncryptedBody.tsx +2 -2
  159. package/apps/shared/components/mail/reading/MessageBody.tsx +6 -6
  160. package/apps/shared/components/mail/reading/MessageCard.tsx +3 -3
  161. package/apps/shared/components/mail/reading/MessageMoreMenu.tsx +258 -258
  162. package/apps/shared/components/mail/reading/MessageSourceDialog.tsx +79 -79
  163. package/apps/shared/components/mail/reading/PendingMessageCard.tsx +1 -1
  164. package/apps/shared/components/mail/reading/bodyContent.ts +3 -3
  165. package/apps/shared/components/mail/reading/bodyHtml.ts +1 -1
  166. package/apps/shared/components/mail/reading/messageExport.ts +59 -59
  167. package/apps/shared/components/mail/reading/printMessage.ts +99 -99
  168. package/apps/shared/components/mail/reading/useMessageActions.ts +450 -443
  169. package/apps/shared/components/mail/unreadStyle.tsx +1 -1
  170. package/apps/shared/components/mail/verificationSeals.ts +129 -125
  171. package/apps/shared/components/mail/writableMailboxes.ts +14 -7
  172. package/apps/shared/components/rules/RuleBuilder.tsx +311 -311
  173. package/apps/shared/components/settings/SigningCertificateCard.tsx +344 -344
  174. package/apps/shared/components/settings/layout/SettingsShell.tsx +8 -6
  175. package/apps/shared/components/sharing/PrincipalListField.tsx +1 -1
  176. package/apps/shared/components/sharing/PrincipalPicker.tsx +1 -1
  177. package/apps/shared/components/sharing/PrincipalResolver.tsx +4 -4
  178. package/apps/shared/components/tasks/TasksSidebar.tsx +7 -5
  179. package/apps/shared/components/tasks/layout/TasksShell.tsx +9 -7
  180. package/apps/shared/keyboard/GlobalShortcuts.tsx +51 -51
  181. package/apps/shared/keyboard/ShortcutProvider.tsx +62 -62
  182. package/apps/shared/keyboard/ShortcutsDialog.tsx +84 -84
  183. package/apps/shared/keyboard/dispatch.ts +124 -124
  184. package/apps/shared/keyboard/format.ts +89 -89
  185. package/apps/shared/keyboard/keymap.ts +114 -114
  186. package/apps/shared/keyboard/registry.ts +65 -65
  187. package/apps/shared/keyboard/targets.ts +79 -79
  188. package/apps/shared/mail/findWellKnownFolderUid.ts +6 -4
  189. package/apps/shared/mail/folderCounts.ts +8 -4
  190. package/apps/shared/mail/folderOfType.ts +51 -49
  191. package/apps/shared/mail/folderTree.ts +143 -143
  192. package/apps/shared/mail/listAllPages.ts +39 -39
  193. package/apps/shared/mail/listSnapshots.ts +2 -2
  194. package/apps/shared/mail/messageReadState.ts +6 -5
  195. package/apps/shared/mail/newMailNotifications.ts +171 -171
  196. package/apps/shared/mail/outbox/composeBridge.ts +2 -2
  197. package/apps/shared/mail/outbox/outboxState.ts +1 -1
  198. package/apps/shared/mail/outbox/outgoingReplies.ts +2 -2
  199. package/apps/shared/mail/outbox/sendDecision.ts +2 -2
  200. package/apps/shared/mail/outbox/sendJob.ts +450 -445
  201. package/apps/shared/mail/outbox/sendOutcomes.ts +160 -155
  202. package/apps/shared/mail/outbox/useOutboxStatus.ts +5 -3
  203. package/apps/shared/mail/permanentDelete.ts +8 -7
  204. package/apps/shared/mail/primaryMailbox.ts +1 -1
  205. package/apps/shared/mail/reportNotices.ts +66 -66
  206. package/apps/shared/mail/senderBlocking.ts +157 -141
  207. package/apps/shared/mail/useMailConnection.ts +207 -205
  208. package/apps/shared/mail/useMailLiveUpdates.ts +277 -277
  209. package/apps/shared/mail/useMailboxUpdateAccess.ts +84 -60
  210. package/apps/shared/mail/useMarkMessageRead.ts +54 -47
  211. package/apps/shared/mail/useNewMailNotifications.ts +178 -178
  212. package/apps/shared/mail/usePermanentDelete.tsx +5 -3
  213. package/apps/shared/navigation/pageTitle.ts +1 -1
  214. package/apps/shared/notifications/NotificationCenter.tsx +1 -1
  215. package/apps/shared/notifications/NotificationHistoryDialog.tsx +2 -2
  216. package/apps/shared/notifications/apiErrors.ts +2 -2
  217. package/apps/shared/notifications/pushStatus.ts +1 -1
  218. package/apps/shared/notifications/store.ts +560 -560
  219. package/apps/shared/notifications/systemErrors.ts +1 -1
  220. package/apps/shared/search/LocalIndexLifecycle.tsx +120 -114
  221. package/apps/shared/search/crossMailboxSearch.ts +3 -3
  222. package/apps/shared/search/localIndexBuilder.ts +493 -481
  223. package/apps/shared/search/localIndexKey.ts +1 -1
  224. package/apps/shared/search/localIndexRpcClient.ts +150 -30
  225. package/apps/shared/search/localIndexTransport.ts +84 -0
  226. package/apps/shared/search/localIndexWorker.ts +1 -1
  227. package/apps/shared/search/searchTier2.ts +3 -3
  228. package/apps/shared/signing/enrollmentStorage.ts +33 -33
  229. package/apps/shared/signing/enrollmentTracker.ts +385 -385
  230. package/apps/shared/signing/enrollmentView.ts +251 -251
  231. package/apps/shared/signing/signingInfo.ts +1 -1
  232. package/apps/shared/signing/useNow.ts +19 -19
  233. package/apps/shared/signing/useSigningEnrollmentWatcher.ts +92 -90
  234. package/apps/shared/styles/app.css +387 -396
  235. package/apps/www/_layout.tsx +2 -2
  236. package/apps/www/calendar/index.tsx +583 -581
  237. package/apps/www/contacts/[uid].tsx +114 -112
  238. package/apps/www/contacts/index.tsx +19 -17
  239. package/apps/www/index.tsx +3021 -3012
  240. package/apps/www/messages/[uid].tsx +141 -139
  241. package/apps/www/settings/auto-reply/index.tsx +138 -136
  242. package/apps/www/settings/blocked-senders/index.tsx +305 -303
  243. package/apps/www/settings/encryption/index.tsx +1296 -1290
  244. package/apps/www/settings/filters/[uid].tsx +184 -179
  245. package/apps/www/settings/filters/_mailFilterRuleConfig.tsx +2 -2
  246. package/apps/www/settings/filters/index.tsx +105 -105
  247. package/apps/www/settings/filters/new/index.tsx +167 -165
  248. package/apps/www/settings/labels/index.tsx +209 -207
  249. package/apps/www/settings/privacy/index.tsx +499 -495
  250. package/apps/www/settings/profile/index.tsx +256 -251
  251. package/apps/www/settings/read-receipts/index.tsx +155 -150
  252. package/apps/www/settings/sharing/index.tsx +259 -259
  253. package/apps/www/settings/signatures/[uid].tsx +175 -175
  254. package/apps/www/settings/signatures/index.tsx +91 -91
  255. package/apps/www/settings/signatures/new/index.tsx +138 -138
  256. package/apps/www/settings/signatures/signatureDefaults.ts +1 -1
  257. package/apps/www/tasks/index.tsx +659 -654
  258. package/dist/apps/admin/_layout.d.ts +1 -1
  259. package/dist/apps/admin/_layout.js +1 -1
  260. package/dist/apps/admin/audit-log/index.d.ts +1 -1
  261. package/dist/apps/admin/audit-log/index.js +4 -4
  262. package/dist/apps/admin/branding/index.js +3 -3
  263. package/dist/apps/admin/data-requests/index.js +8 -8
  264. package/dist/apps/admin/distribution-lists/[uid].js +3 -3
  265. package/dist/apps/admin/distribution-lists/index.js +4 -4
  266. package/dist/apps/admin/distribution-lists/new/index.js +5 -5
  267. package/dist/apps/admin/domains/[uid].js +6 -6
  268. package/dist/apps/admin/domains/index.js +4 -4
  269. package/dist/apps/admin/domains/new/index.js +5 -5
  270. package/dist/apps/admin/encryption-policy/index.js +1 -1
  271. package/dist/apps/admin/escrow-scopes/[uid].d.ts +1 -1
  272. package/dist/apps/admin/escrow-scopes/[uid].js +7 -7
  273. package/dist/apps/admin/escrow-scopes/index.js +4 -4
  274. package/dist/apps/admin/escrow-scopes/new/index.js +5 -5
  275. package/dist/apps/admin/index.js +6 -6
  276. package/dist/apps/admin/ingest-queue/index.js +4 -4
  277. package/dist/apps/admin/mailbox-policy/index.js +1 -1
  278. package/dist/apps/admin/mailboxes/[uid].js +5 -5
  279. package/dist/apps/admin/quarantine/index.js +5 -5
  280. package/dist/apps/admin/retention-policy/index.js +3 -3
  281. package/dist/apps/admin/signing-certificates/index.js +5 -5
  282. package/dist/apps/admin/transport-rules/[uid].js +5 -5
  283. package/dist/apps/admin/transport-rules/_transportRuleConfig.d.ts +1 -1
  284. package/dist/apps/admin/transport-rules/_transportRuleConfig.js +2 -2
  285. package/dist/apps/admin/transport-rules/index.js +4 -4
  286. package/dist/apps/admin/transport-rules/new/index.js +5 -5
  287. package/dist/apps/escrow/_layout.d.ts +1 -1
  288. package/dist/apps/escrow/audit-log/index.d.ts +1 -1
  289. package/dist/apps/escrow/audit-log/index.js +4 -4
  290. package/dist/apps/escrow/index.js +4 -4
  291. package/dist/apps/escrow/matters/[uid].js +10 -10
  292. package/dist/apps/escrow/matters/new/index.js +6 -6
  293. package/dist/apps/shared/appearance/AppearanceForm.js +3 -3
  294. package/dist/apps/shared/appearance/AppearanceHead.js +1 -1
  295. package/dist/apps/shared/appearance/AppearanceProvider.d.ts +1 -1
  296. package/dist/apps/shared/appearance/AppearanceProvider.js +3 -3
  297. package/dist/apps/shared/appearance/appearanceCache.d.ts +1 -1
  298. package/dist/apps/shared/appearance/appearanceCache.js +1 -1
  299. package/dist/apps/shared/appearance/appearanceContext.d.ts +1 -1
  300. package/dist/apps/shared/appearance/theme.d.ts +1 -1
  301. package/dist/apps/shared/auth/adminAccess.js +1 -1
  302. package/dist/apps/shared/calendar/bookingPlugin.js +1 -1
  303. package/dist/apps/shared/calendar/calendarLiveUpdates.d.ts +1 -1
  304. package/dist/apps/shared/calendar/calendarReminders.d.ts +1 -1
  305. package/dist/apps/shared/calendar/useCalendarReminders.js +1 -1
  306. package/dist/apps/shared/components/admin/diagnostics/DiagnosticsManager.js +1 -1
  307. package/dist/apps/shared/components/admin/diagnostics/InstalledPlugins.d.ts +1 -1
  308. package/dist/apps/shared/components/admin/diagnostics/InstalledPlugins.js +2 -2
  309. package/dist/apps/shared/components/admin/diagnostics/LogsPanel.js +2 -2
  310. package/dist/apps/shared/components/admin/diagnostics/PackagesTable.js +1 -1
  311. package/dist/apps/shared/components/admin/diagnostics/RuntimePanel.js +1 -1
  312. package/dist/apps/shared/components/admin/diagnostics/SystemPanel.js +2 -2
  313. package/dist/apps/shared/components/admin/diagnostics/VersionsPanel.js +1 -1
  314. package/dist/apps/shared/components/admin/diagnostics/diagnosticsApi.js +1 -1
  315. package/dist/apps/shared/components/admin/diagnostics/format.js +1 -1
  316. package/dist/apps/shared/components/admin/diagnostics/logClient.js +1 -1
  317. package/dist/apps/shared/components/admin/distributionLists/MemberListCard.d.ts +1 -1
  318. package/dist/apps/shared/components/admin/distributionLists/MemberListCard.js +4 -4
  319. package/dist/apps/shared/components/admin/elevation.js +1 -1
  320. package/dist/apps/shared/components/admin/escrowScopes/EscrowScopeKeyAndHoldersFields.js +3 -3
  321. package/dist/apps/shared/components/admin/layout/AdminShell.d.ts +1 -1
  322. package/dist/apps/shared/components/admin/layout/AdminShell.js +8 -8
  323. package/dist/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.d.ts +1 -1
  324. package/dist/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.js +6 -6
  325. package/dist/apps/shared/components/admin/mailboxes/EscrowScopeCard.d.ts +1 -1
  326. package/dist/apps/shared/components/admin/mailboxes/EscrowScopeCard.js +10 -8
  327. package/dist/apps/shared/components/admin/mailboxes/LeftoverMailboxesSection.js +4 -4
  328. package/dist/apps/shared/components/admin/mailboxes/MailboxTable.d.ts +1 -1
  329. package/dist/apps/shared/components/admin/mailboxes/ResourceSettingsCard.d.ts +1 -1
  330. package/dist/apps/shared/components/admin/mailboxes/ResourceSettingsCard.js +7 -5
  331. package/dist/apps/shared/components/admin/mailboxes/ShareAccessCard.js +5 -5
  332. package/dist/apps/shared/components/admin/settings/BrandingForm.d.ts +1 -1
  333. package/dist/apps/shared/components/admin/settings/BrandingForm.js +8 -8
  334. package/dist/apps/shared/components/admin/settings/DomainDnsSetup.d.ts +1 -1
  335. package/dist/apps/shared/components/admin/settings/DomainDnsSetup.js +5 -5
  336. package/dist/apps/shared/components/admin/settings/EncryptionPolicyForm.d.ts +1 -1
  337. package/dist/apps/shared/components/admin/settings/EncryptionPolicyForm.js +4 -4
  338. package/dist/apps/shared/components/admin/settings/LoadedSettingsForm.js +2 -2
  339. package/dist/apps/shared/components/admin/settings/MailboxCreateForm.d.ts +1 -1
  340. package/dist/apps/shared/components/admin/settings/MailboxCreateForm.js +14 -12
  341. package/dist/apps/shared/components/admin/settings/MailboxPolicyForm.d.ts +1 -1
  342. package/dist/apps/shared/components/admin/settings/MailboxPolicyForm.js +4 -4
  343. package/dist/apps/shared/components/admin/settings/PluginsManager.js +5 -5
  344. package/dist/apps/shared/components/admin/settings/RetentionPolicyForm.d.ts +1 -1
  345. package/dist/apps/shared/components/admin/settings/RetentionPolicyForm.js +5 -5
  346. package/dist/apps/shared/components/admin/setup/EscrowSetupStep.js +7 -7
  347. package/dist/apps/shared/components/admin/setup/SetupWizard.js +26 -22
  348. package/dist/apps/shared/components/admin/signOut.js +1 -1
  349. package/dist/apps/shared/components/admin/usePagedList.js +2 -2
  350. package/dist/apps/shared/components/calendar/AppointmentQuickForm.js +3 -3
  351. package/dist/apps/shared/components/calendar/CalendarListSidebar.d.ts +1 -1
  352. package/dist/apps/shared/components/calendar/CalendarListSidebar.js +2 -2
  353. package/dist/apps/shared/components/calendar/DescriptionEditor.js +1 -1
  354. package/dist/apps/shared/components/calendar/EventDescriptionView.js +1 -1
  355. package/dist/apps/shared/components/calendar/EventDetails.d.ts +2 -2
  356. package/dist/apps/shared/components/calendar/EventDetails.js +16 -14
  357. package/dist/apps/shared/components/calendar/EventEditor.d.ts +2 -2
  358. package/dist/apps/shared/components/calendar/EventEditor.js +22 -20
  359. package/dist/apps/shared/components/calendar/EventExpandedForm.js +2 -2
  360. package/dist/apps/shared/components/calendar/EventFormParts.d.ts +1 -1
  361. package/dist/apps/shared/components/calendar/EventFormParts.js +1 -1
  362. package/dist/apps/shared/components/calendar/EventModal.d.ts +2 -2
  363. package/dist/apps/shared/components/calendar/EventModal.js +3 -3
  364. package/dist/apps/shared/components/calendar/EventQuickForm.js +3 -3
  365. package/dist/apps/shared/components/calendar/EventShell.js +1 -1
  366. package/dist/apps/shared/components/calendar/FindATime.js +6 -4
  367. package/dist/apps/shared/components/calendar/GuestInput.d.ts +2 -2
  368. package/dist/apps/shared/components/calendar/MonthView.d.ts +1 -1
  369. package/dist/apps/shared/components/calendar/MonthView.js +1 -1
  370. package/dist/apps/shared/components/calendar/QuickCreateFaces.js +1 -1
  371. package/dist/apps/shared/components/calendar/QuickFaceFrame.js +1 -1
  372. package/dist/apps/shared/components/calendar/RecurrenceEditor.d.ts +1 -1
  373. package/dist/apps/shared/components/calendar/RecurrenceEditor.js +1 -1
  374. package/dist/apps/shared/components/calendar/RequestChangeForm.js +8 -6
  375. package/dist/apps/shared/components/calendar/ResourcePicker.d.ts +1 -1
  376. package/dist/apps/shared/components/calendar/ResourcePicker.js +7 -5
  377. package/dist/apps/shared/components/calendar/SplitDayView.d.ts +1 -1
  378. package/dist/apps/shared/components/calendar/TaskQuickForm.d.ts +1 -1
  379. package/dist/apps/shared/components/calendar/TaskQuickForm.js +9 -7
  380. package/dist/apps/shared/components/calendar/TimeGridView.d.ts +1 -1
  381. package/dist/apps/shared/components/calendar/TimeGridView.js +1 -1
  382. package/dist/apps/shared/components/calendar/allDay.d.ts +2 -2
  383. package/dist/apps/shared/components/calendar/allDay.js +1 -1
  384. package/dist/apps/shared/components/calendar/eventDialogFields.d.ts +2 -2
  385. package/dist/apps/shared/components/calendar/eventDialogFields.js +2 -2
  386. package/dist/apps/shared/components/calendar/eventForm.d.ts +3 -3
  387. package/dist/apps/shared/components/calendar/eventFormat.d.ts +1 -1
  388. package/dist/apps/shared/components/calendar/eventFormat.js +2 -2
  389. package/dist/apps/shared/components/calendar/findTimeGrid.d.ts +1 -1
  390. package/dist/apps/shared/components/calendar/findTimeGrid.js +1 -1
  391. package/dist/apps/shared/components/calendar/layout/CalendarShell.d.ts +1 -1
  392. package/dist/apps/shared/components/calendar/layout/CalendarShell.js +11 -9
  393. package/dist/apps/shared/components/contacts/ContactDetailPane.d.ts +1 -1
  394. package/dist/apps/shared/components/contacts/ContactDetailPane.js +2 -2
  395. package/dist/apps/shared/components/contacts/ContactForm.d.ts +2 -2
  396. package/dist/apps/shared/components/contacts/ContactForm.js +12 -8
  397. package/dist/apps/shared/components/contacts/ContactsSidebar.d.ts +1 -1
  398. package/dist/apps/shared/components/contacts/ContactsSidebar.js +7 -5
  399. package/dist/apps/shared/components/contacts/KeyChangeReview.d.ts +1 -1
  400. package/dist/apps/shared/components/contacts/KeyChangeReview.js +5 -5
  401. package/dist/apps/shared/components/contacts/contactKeys.d.ts +2 -2
  402. package/dist/apps/shared/components/contacts/contactKeys.js +2 -2
  403. package/dist/apps/shared/components/contacts/layout/ContactsShell.d.ts +1 -1
  404. package/dist/apps/shared/components/contacts/layout/ContactsShell.js +9 -7
  405. package/dist/apps/shared/components/escrow/layout/EscrowShell.js +7 -7
  406. package/dist/apps/shared/components/forms/StringListField.js +1 -1
  407. package/dist/apps/shared/components/layout/AppShell.d.ts +2 -2
  408. package/dist/apps/shared/components/layout/AppShell.js +14 -10
  409. package/dist/apps/shared/components/layout/BrandingChrome.d.ts +1 -1
  410. package/dist/apps/shared/components/layout/KeyEnrollmentGate.d.ts +1 -1
  411. package/dist/apps/shared/components/layout/KeyEnrollmentGate.js +9 -9
  412. package/dist/apps/shared/components/layout/MailboxProvisioning.js +8 -6
  413. package/dist/apps/shared/components/layout/RecoveryCodeUnlock.d.ts +1 -1
  414. package/dist/apps/shared/components/layout/RecoveryCodeUnlock.js +9 -9
  415. package/dist/apps/shared/components/layout/UnlockPromptProvider.d.ts +2 -2
  416. package/dist/apps/shared/components/layout/UnlockPromptProvider.js +5 -5
  417. package/dist/apps/shared/components/layout/UserMenu.js +6 -4
  418. package/dist/apps/shared/components/mail/ConversationList.d.ts +2 -2
  419. package/dist/apps/shared/components/mail/ConversationList.js +6 -4
  420. package/dist/apps/shared/components/mail/ConversationThreadPane.d.ts +3 -3
  421. package/dist/apps/shared/components/mail/ConversationThreadPane.js +13 -11
  422. package/dist/apps/shared/components/mail/InviteCard.js +10 -8
  423. package/dist/apps/shared/components/mail/LazyReadingPane.js +2 -2
  424. package/dist/apps/shared/components/mail/MailAddress.d.ts +1 -1
  425. package/dist/apps/shared/components/mail/MailAddress.js +1 -1
  426. package/dist/apps/shared/components/mail/MailListToolbar.d.ts +2 -2
  427. package/dist/apps/shared/components/mail/MailSelectionBar.d.ts +2 -2
  428. package/dist/apps/shared/components/mail/MenuButton.js +1 -1
  429. package/dist/apps/shared/components/mail/MessageDetailPane.d.ts +3 -3
  430. package/dist/apps/shared/components/mail/MessageDetailPane.js +30 -28
  431. package/dist/apps/shared/components/mail/MoveToFolderDialog.d.ts +1 -1
  432. package/dist/apps/shared/components/mail/MoveToFolderDialog.js +8 -6
  433. package/dist/apps/shared/components/mail/OutboxRowStatus.d.ts +1 -1
  434. package/dist/apps/shared/components/mail/PermanentDeleteDialog.js +2 -2
  435. package/dist/apps/shared/components/mail/compose/ComposeContext.d.ts +10 -1
  436. package/dist/apps/shared/components/mail/compose/ComposeContext.js +4 -2
  437. package/dist/apps/shared/components/mail/compose/ComposeWindow.d.ts +7 -1
  438. package/dist/apps/shared/components/mail/compose/ComposeWindow.js +54 -31
  439. package/dist/apps/shared/components/mail/compose/ComposeWindowPlaceholder.js +4 -4
  440. package/dist/apps/shared/components/mail/compose/EmojiPicker.js +2 -2
  441. package/dist/apps/shared/components/mail/compose/GifPicker.js +3 -3
  442. package/dist/apps/shared/components/mail/compose/RecipientInput.d.ts +1 -1
  443. package/dist/apps/shared/components/mail/compose/RecipientInput.js +1 -1
  444. package/dist/apps/shared/components/mail/compose/ScheduleSendPicker.js +1 -1
  445. package/dist/apps/shared/components/mail/compose/encryptionRequirement.d.ts +2 -2
  446. package/dist/apps/shared/components/mail/compose/encryptionRequirement.js +1 -1
  447. package/dist/apps/shared/components/mail/compose/quotedBody.d.ts +3 -3
  448. package/dist/apps/shared/components/mail/compose/quotedBody.js +3 -3
  449. package/dist/apps/shared/components/mail/compose/recipients.d.ts +1 -1
  450. package/dist/apps/shared/components/mail/invite/InviteRowChip.d.ts +1 -1
  451. package/dist/apps/shared/components/mail/invite/InviteRsvpPopover.d.ts +1 -1
  452. package/dist/apps/shared/components/mail/invite/InviteRsvpPopover.js +9 -7
  453. package/dist/apps/shared/components/mail/invite/InviteTimeline.d.ts +1 -1
  454. package/dist/apps/shared/components/mail/invite/ProposeTimeForm.d.ts +1 -1
  455. package/dist/apps/shared/components/mail/invite/ProposeTimeForm.js +1 -1
  456. package/dist/apps/shared/components/mail/invite/inviteFormat.d.ts +2 -2
  457. package/dist/apps/shared/components/mail/invite/inviteStore.d.ts +9 -3
  458. package/dist/apps/shared/components/mail/invite/inviteStore.js +13 -6
  459. package/dist/apps/shared/components/mail/labelMenu.d.ts +1 -1
  460. package/dist/apps/shared/components/mail/labelMenu.js +9 -7
  461. package/dist/apps/shared/components/mail/layout/MailShell.d.ts +1 -1
  462. package/dist/apps/shared/components/mail/layout/MailShell.js +3 -3
  463. package/dist/apps/shared/components/mail/listPreferences.d.ts +2 -2
  464. package/dist/apps/shared/components/mail/listPreferences.js +1 -1
  465. package/dist/apps/shared/components/mail/pinnedSigners.d.ts +12 -5
  466. package/dist/apps/shared/components/mail/pinnedSigners.js +37 -18
  467. package/dist/apps/shared/components/mail/reading/EncryptedBody.js +2 -2
  468. package/dist/apps/shared/components/mail/reading/MessageBody.d.ts +2 -2
  469. package/dist/apps/shared/components/mail/reading/MessageBody.js +4 -4
  470. package/dist/apps/shared/components/mail/reading/MessageCard.d.ts +1 -1
  471. package/dist/apps/shared/components/mail/reading/MessageCard.js +2 -2
  472. package/dist/apps/shared/components/mail/reading/MessageSourceDialog.js +3 -3
  473. package/dist/apps/shared/components/mail/reading/PendingMessageCard.js +1 -1
  474. package/dist/apps/shared/components/mail/reading/bodyContent.d.ts +2 -2
  475. package/dist/apps/shared/components/mail/reading/bodyContent.js +2 -2
  476. package/dist/apps/shared/components/mail/reading/bodyHtml.js +1 -1
  477. package/dist/apps/shared/components/mail/reading/messageExport.js +1 -1
  478. package/dist/apps/shared/components/mail/reading/printMessage.d.ts +2 -2
  479. package/dist/apps/shared/components/mail/reading/printMessage.js +11 -11
  480. package/dist/apps/shared/components/mail/reading/useMessageActions.d.ts +1 -1
  481. package/dist/apps/shared/components/mail/reading/useMessageActions.js +18 -16
  482. package/dist/apps/shared/components/mail/unreadStyle.d.ts +1 -1
  483. package/dist/apps/shared/components/mail/verificationSeals.d.ts +27 -6
  484. package/dist/apps/shared/components/mail/verificationSeals.js +15 -11
  485. package/dist/apps/shared/components/mail/writableMailboxes.d.ts +8 -3
  486. package/dist/apps/shared/components/mail/writableMailboxes.js +12 -6
  487. package/dist/apps/shared/components/rules/RuleBuilder.js +1 -1
  488. package/dist/apps/shared/components/settings/SigningCertificateCard.d.ts +1 -1
  489. package/dist/apps/shared/components/settings/SigningCertificateCard.js +3 -3
  490. package/dist/apps/shared/components/settings/layout/SettingsShell.d.ts +1 -1
  491. package/dist/apps/shared/components/settings/layout/SettingsShell.js +8 -6
  492. package/dist/apps/shared/components/sharing/PrincipalListField.d.ts +1 -1
  493. package/dist/apps/shared/components/sharing/PrincipalPicker.d.ts +1 -1
  494. package/dist/apps/shared/components/sharing/PrincipalPicker.js +1 -1
  495. package/dist/apps/shared/components/sharing/PrincipalResolver.d.ts +1 -1
  496. package/dist/apps/shared/components/sharing/PrincipalResolver.js +3 -3
  497. package/dist/apps/shared/components/tasks/TasksSidebar.d.ts +1 -1
  498. package/dist/apps/shared/components/tasks/TasksSidebar.js +7 -5
  499. package/dist/apps/shared/components/tasks/layout/TasksShell.d.ts +1 -1
  500. package/dist/apps/shared/components/tasks/layout/TasksShell.js +9 -7
  501. package/dist/apps/shared/keyboard/ShortcutsDialog.js +1 -1
  502. package/dist/apps/shared/mail/findWellKnownFolderUid.d.ts +5 -3
  503. package/dist/apps/shared/mail/findWellKnownFolderUid.js +5 -4
  504. package/dist/apps/shared/mail/folderCounts.d.ts +1 -1
  505. package/dist/apps/shared/mail/folderCounts.js +6 -4
  506. package/dist/apps/shared/mail/folderOfType.d.ts +3 -2
  507. package/dist/apps/shared/mail/folderOfType.js +4 -4
  508. package/dist/apps/shared/mail/folderTree.d.ts +1 -1
  509. package/dist/apps/shared/mail/listSnapshots.d.ts +2 -2
  510. package/dist/apps/shared/mail/messageReadState.d.ts +4 -3
  511. package/dist/apps/shared/mail/messageReadState.js +5 -5
  512. package/dist/apps/shared/mail/newMailNotifications.d.ts +1 -1
  513. package/dist/apps/shared/mail/newMailNotifications.js +1 -1
  514. package/dist/apps/shared/mail/outbox/composeBridge.d.ts +2 -2
  515. package/dist/apps/shared/mail/outbox/outboxState.d.ts +1 -1
  516. package/dist/apps/shared/mail/outbox/outgoingReplies.d.ts +2 -2
  517. package/dist/apps/shared/mail/outbox/sendDecision.d.ts +2 -2
  518. package/dist/apps/shared/mail/outbox/sendDecision.js +1 -1
  519. package/dist/apps/shared/mail/outbox/sendJob.d.ts +10 -6
  520. package/dist/apps/shared/mail/outbox/sendJob.js +39 -35
  521. package/dist/apps/shared/mail/outbox/sendOutcomes.d.ts +6 -3
  522. package/dist/apps/shared/mail/outbox/sendOutcomes.js +19 -15
  523. package/dist/apps/shared/mail/outbox/useOutboxStatus.js +5 -3
  524. package/dist/apps/shared/mail/permanentDelete.d.ts +4 -3
  525. package/dist/apps/shared/mail/permanentDelete.js +8 -8
  526. package/dist/apps/shared/mail/primaryMailbox.d.ts +1 -1
  527. package/dist/apps/shared/mail/primaryMailbox.js +1 -1
  528. package/dist/apps/shared/mail/reportNotices.d.ts +1 -1
  529. package/dist/apps/shared/mail/senderBlocking.d.ts +5 -4
  530. package/dist/apps/shared/mail/senderBlocking.js +19 -16
  531. package/dist/apps/shared/mail/useMailConnection.d.ts +1 -1
  532. package/dist/apps/shared/mail/useMailConnection.js +12 -10
  533. package/dist/apps/shared/mail/useMailLiveUpdates.d.ts +2 -2
  534. package/dist/apps/shared/mail/useMailLiveUpdates.js +2 -2
  535. package/dist/apps/shared/mail/useMailboxUpdateAccess.d.ts +3 -2
  536. package/dist/apps/shared/mail/useMailboxUpdateAccess.js +31 -10
  537. package/dist/apps/shared/mail/useMarkMessageRead.d.ts +1 -1
  538. package/dist/apps/shared/mail/useMarkMessageRead.js +5 -3
  539. package/dist/apps/shared/mail/useNewMailNotifications.d.ts +1 -1
  540. package/dist/apps/shared/mail/usePermanentDelete.d.ts +1 -1
  541. package/dist/apps/shared/mail/usePermanentDelete.js +4 -2
  542. package/dist/apps/shared/navigation/pageTitle.d.ts +1 -1
  543. package/dist/apps/shared/notifications/NotificationCenter.js +1 -1
  544. package/dist/apps/shared/notifications/NotificationHistoryDialog.js +2 -2
  545. package/dist/apps/shared/notifications/apiErrors.js +2 -2
  546. package/dist/apps/shared/notifications/pushStatus.js +1 -1
  547. package/dist/apps/shared/notifications/systemErrors.js +1 -1
  548. package/dist/apps/shared/search/LocalIndexLifecycle.d.ts +2 -2
  549. package/dist/apps/shared/search/LocalIndexLifecycle.js +15 -10
  550. package/dist/apps/shared/search/crossMailboxSearch.d.ts +1 -1
  551. package/dist/apps/shared/search/crossMailboxSearch.js +2 -2
  552. package/dist/apps/shared/search/localIndexBuilder.d.ts +4 -3
  553. package/dist/apps/shared/search/localIndexBuilder.js +15 -12
  554. package/dist/apps/shared/search/localIndexKey.js +1 -1
  555. package/dist/apps/shared/search/localIndexRpcClient.d.ts +43 -31
  556. package/dist/apps/shared/search/localIndexRpcClient.js +113 -20
  557. package/dist/apps/shared/search/localIndexTransport.d.ts +77 -0
  558. package/dist/apps/shared/search/localIndexTransport.js +1 -0
  559. package/dist/apps/shared/search/localIndexWorker.d.ts +1 -1
  560. package/dist/apps/shared/search/searchTier2.d.ts +3 -3
  561. package/dist/apps/shared/signing/enrollmentTracker.d.ts +1 -1
  562. package/dist/apps/shared/signing/enrollmentTracker.js +3 -3
  563. package/dist/apps/shared/signing/enrollmentView.d.ts +1 -1
  564. package/dist/apps/shared/signing/signingInfo.d.ts +1 -1
  565. package/dist/apps/shared/signing/signingInfo.js +1 -1
  566. package/dist/apps/shared/signing/useSigningEnrollmentWatcher.d.ts +1 -1
  567. package/dist/apps/shared/signing/useSigningEnrollmentWatcher.js +5 -3
  568. package/dist/apps/shared/styles/app.css +387 -396
  569. package/dist/apps/www/_layout.d.ts +1 -1
  570. package/dist/apps/www/_layout.js +1 -1
  571. package/dist/apps/www/calendar/index.d.ts +1 -1
  572. package/dist/apps/www/calendar/index.js +20 -18
  573. package/dist/apps/www/contacts/[uid].d.ts +1 -1
  574. package/dist/apps/www/contacts/[uid].js +8 -6
  575. package/dist/apps/www/contacts/index.d.ts +1 -1
  576. package/dist/apps/www/contacts/index.js +19 -17
  577. package/dist/apps/www/index.d.ts +1 -1
  578. package/dist/apps/www/index.js +54 -50
  579. package/dist/apps/www/messages/[uid].d.ts +1 -1
  580. package/dist/apps/www/messages/[uid].js +11 -9
  581. package/dist/apps/www/settings/appearance/index.d.ts +1 -1
  582. package/dist/apps/www/settings/auto-reply/index.d.ts +1 -1
  583. package/dist/apps/www/settings/auto-reply/index.js +6 -4
  584. package/dist/apps/www/settings/blocked-senders/index.d.ts +1 -1
  585. package/dist/apps/www/settings/blocked-senders/index.js +6 -4
  586. package/dist/apps/www/settings/encryption/index.d.ts +1 -1
  587. package/dist/apps/www/settings/encryption/index.js +31 -29
  588. package/dist/apps/www/settings/filters/[uid].d.ts +1 -1
  589. package/dist/apps/www/settings/filters/[uid].js +11 -9
  590. package/dist/apps/www/settings/filters/_mailFilterRuleConfig.d.ts +2 -2
  591. package/dist/apps/www/settings/filters/index.d.ts +1 -1
  592. package/dist/apps/www/settings/filters/index.js +4 -4
  593. package/dist/apps/www/settings/filters/new/index.d.ts +1 -1
  594. package/dist/apps/www/settings/filters/new/index.js +10 -8
  595. package/dist/apps/www/settings/labels/index.d.ts +1 -1
  596. package/dist/apps/www/settings/labels/index.js +12 -10
  597. package/dist/apps/www/settings/privacy/index.d.ts +1 -1
  598. package/dist/apps/www/settings/privacy/index.js +18 -14
  599. package/dist/apps/www/settings/profile/index.d.ts +1 -1
  600. package/dist/apps/www/settings/profile/index.js +7 -5
  601. package/dist/apps/www/settings/read-receipts/index.d.ts +1 -1
  602. package/dist/apps/www/settings/read-receipts/index.js +5 -3
  603. package/dist/apps/www/settings/sharing/index.d.ts +1 -1
  604. package/dist/apps/www/settings/sharing/index.js +6 -6
  605. package/dist/apps/www/settings/signatures/[uid].d.ts +1 -1
  606. package/dist/apps/www/settings/signatures/[uid].js +5 -5
  607. package/dist/apps/www/settings/signatures/index.d.ts +1 -1
  608. package/dist/apps/www/settings/signatures/index.js +4 -4
  609. package/dist/apps/www/settings/signatures/new/index.d.ts +1 -1
  610. package/dist/apps/www/settings/signatures/new/index.js +4 -4
  611. package/dist/apps/www/settings/signatures/signatureDefaults.d.ts +1 -1
  612. package/dist/apps/www/settings/signatures/signatureDefaults.js +1 -1
  613. package/dist/apps/www/tasks/index.d.ts +1 -1
  614. package/dist/apps/www/tasks/index.js +17 -15
  615. package/dist/lib/admin/auditLogApi.d.ts +32 -0
  616. package/dist/lib/admin/auditLogApi.js +27 -0
  617. package/dist/lib/admin/distributionListsApi.d.ts +47 -0
  618. package/dist/lib/admin/distributionListsApi.js +34 -0
  619. package/dist/lib/admin/domainsApi.d.ts +75 -0
  620. package/dist/lib/admin/domainsApi.js +44 -0
  621. package/dist/lib/admin/escrowAccessRequestsApi.d.ts +79 -0
  622. package/dist/lib/admin/escrowAccessRequestsApi.js +46 -0
  623. package/dist/lib/admin/escrowAuditLogApi.d.ts +66 -0
  624. package/dist/lib/admin/escrowAuditLogApi.js +31 -0
  625. package/dist/lib/admin/escrowScopesApi.d.ts +78 -0
  626. package/dist/lib/admin/escrowScopesApi.js +50 -0
  627. package/dist/lib/admin/leftoverMailboxApi.d.ts +73 -0
  628. package/dist/lib/admin/leftoverMailboxApi.js +67 -0
  629. package/dist/lib/admin/mailboxPolicyApi.d.ts +27 -0
  630. package/dist/lib/admin/mailboxPolicyApi.js +21 -0
  631. package/dist/lib/admin/matterExportApi.d.ts +40 -0
  632. package/dist/lib/admin/matterExportApi.js +39 -0
  633. package/dist/lib/admin/matterSearchApi.d.ts +20 -0
  634. package/dist/lib/admin/matterSearchApi.js +27 -0
  635. package/dist/lib/admin/mattersApi.d.ts +56 -0
  636. package/dist/lib/admin/mattersApi.js +40 -0
  637. package/dist/lib/admin/pluginsApi.d.ts +265 -0
  638. package/dist/lib/admin/pluginsApi.js +102 -0
  639. package/dist/lib/admin/retentionPolicyApi.d.ts +32 -0
  640. package/dist/lib/admin/retentionPolicyApi.js +29 -0
  641. package/dist/lib/admin/setupApi.d.ts +23 -0
  642. package/dist/lib/admin/setupApi.js +26 -0
  643. package/dist/lib/admin/transportRulesApi.d.ts +66 -0
  644. package/dist/lib/admin/transportRulesApi.js +43 -0
  645. package/dist/lib/appearance/preferencesApi.d.ts +128 -0
  646. package/dist/lib/appearance/preferencesApi.js +257 -0
  647. package/dist/lib/auth/profileApi.d.ts +33 -0
  648. package/dist/lib/auth/profileApi.js +52 -0
  649. package/dist/lib/auth/session.d.ts +70 -0
  650. package/dist/lib/auth/session.js +210 -0
  651. package/dist/lib/branding/brandingApi.d.ts +47 -0
  652. package/dist/lib/branding/brandingApi.js +61 -0
  653. package/dist/lib/branding/useBranding.d.ts +23 -0
  654. package/dist/lib/branding/useBranding.js +65 -0
  655. package/dist/lib/calendar/calendarApi.d.ts +230 -0
  656. package/dist/lib/calendar/calendarApi.js +106 -0
  657. package/dist/lib/calendar/calendarColors.d.ts +18 -0
  658. package/dist/lib/calendar/calendarColors.js +39 -0
  659. package/dist/lib/calendar/calendarDragIds.d.ts +42 -0
  660. package/dist/lib/calendar/calendarDragIds.js +92 -0
  661. package/dist/lib/calendar/calendarMutations.d.ts +68 -0
  662. package/dist/lib/calendar/calendarMutations.js +190 -0
  663. package/dist/lib/calendar/eventDescription.d.ts +43 -0
  664. package/dist/lib/calendar/eventDescription.js +195 -0
  665. package/dist/lib/calendar/freeBusyApi.d.ts +100 -0
  666. package/dist/lib/calendar/freeBusyApi.js +119 -0
  667. package/dist/lib/calendar/inviteApi.d.ts +121 -0
  668. package/dist/lib/calendar/inviteApi.js +54 -0
  669. package/dist/lib/calendar/recurrence.d.ts +60 -0
  670. package/dist/lib/calendar/recurrence.js +225 -0
  671. package/dist/lib/components/avatar/ContactAvatar.d.ts +8 -0
  672. package/dist/lib/components/avatar/ContactAvatar.js +26 -0
  673. package/dist/lib/components/buttons/Button.d.ts +9 -0
  674. package/dist/lib/components/buttons/Button.js +14 -0
  675. package/dist/lib/components/buttons/CopyButton.d.ts +18 -0
  676. package/dist/lib/components/buttons/CopyButton.js +14 -0
  677. package/dist/lib/components/feedback/Alert.d.ts +4 -0
  678. package/dist/lib/components/feedback/Alert.js +4 -0
  679. package/dist/lib/components/feedback/Skeleton.d.ts +21 -0
  680. package/dist/lib/components/feedback/Skeleton.js +14 -0
  681. package/dist/lib/components/forms/FormField.d.ts +8 -0
  682. package/dist/lib/components/forms/FormField.js +5 -0
  683. package/dist/lib/components/navigation/BottomTabBar.d.ts +27 -0
  684. package/dist/lib/components/navigation/BottomTabBar.js +32 -0
  685. package/dist/lib/components/overlays/Drawer.d.ts +20 -0
  686. package/dist/lib/components/overlays/Drawer.js +27 -0
  687. package/dist/lib/components/overlays/Modal.d.ts +17 -0
  688. package/dist/lib/components/overlays/Modal.js +25 -0
  689. package/dist/lib/components/overlays/PopoverPortal.d.ts +23 -0
  690. package/dist/lib/components/overlays/PopoverPortal.js +53 -0
  691. package/dist/lib/components/overlays/overlayStack.d.ts +31 -0
  692. package/dist/lib/components/overlays/overlayStack.js +143 -0
  693. package/dist/lib/components/pickers/MiniDatePicker.d.ts +13 -0
  694. package/dist/lib/components/pickers/MiniDatePicker.js +42 -0
  695. package/dist/lib/contacts/contactsApi.d.ts +174 -0
  696. package/dist/lib/contacts/contactsApi.js +139 -0
  697. package/dist/lib/contacts/vcard.d.ts +23 -0
  698. package/dist/lib/contacts/vcard.js +179 -0
  699. package/dist/lib/crypto/composeSecurity.d.ts +67 -0
  700. package/dist/lib/crypto/composeSecurity.js +93 -0
  701. package/dist/lib/crypto/encoding.d.ts +9 -0
  702. package/dist/lib/crypto/encoding.js +32 -0
  703. package/dist/lib/crypto/escrowKeys.d.ts +25 -0
  704. package/dist/lib/crypto/escrowKeys.js +59 -0
  705. package/dist/lib/crypto/idleTimeout.d.ts +16 -0
  706. package/dist/lib/crypto/idleTimeout.js +47 -0
  707. package/dist/lib/crypto/keySession.d.ts +159 -0
  708. package/dist/lib/crypto/keySession.js +367 -0
  709. package/dist/lib/crypto/keys.d.ts +50 -0
  710. package/dist/lib/crypto/keys.js +89 -0
  711. package/dist/lib/crypto/keyvaultApi.d.ts +394 -0
  712. package/dist/lib/crypto/keyvaultApi.js +350 -0
  713. package/dist/lib/crypto/masterKey.d.ts +59 -0
  714. package/dist/lib/crypto/masterKey.js +104 -0
  715. package/dist/lib/crypto/masterKeyWraps.d.ts +108 -0
  716. package/dist/lib/crypto/masterKeyWraps.js +228 -0
  717. package/dist/lib/crypto/messageSecurity.d.ts +248 -0
  718. package/dist/lib/crypto/messageSecurity.js +367 -0
  719. package/dist/lib/crypto/mime.d.ts +143 -0
  720. package/dist/lib/crypto/mime.js +504 -0
  721. package/dist/lib/crypto/passkeyUnlock.d.ts +20 -0
  722. package/dist/lib/crypto/passkeyUnlock.js +79 -0
  723. package/dist/lib/crypto/passwordUnlock.d.ts +39 -0
  724. package/dist/lib/crypto/passwordUnlock.js +73 -0
  725. package/dist/lib/crypto/recoveryCode.d.ts +28 -0
  726. package/dist/lib/crypto/recoveryCode.js +86 -0
  727. package/dist/lib/crypto/signingProviderApi.d.ts +95 -0
  728. package/dist/lib/crypto/signingProviderApi.js +60 -0
  729. package/dist/lib/crypto/smime.d.ts +128 -0
  730. package/dist/lib/crypto/smime.js +402 -0
  731. package/dist/lib/crypto/smimeMessage.d.ts +132 -0
  732. package/dist/lib/crypto/smimeMessage.js +341 -0
  733. package/dist/lib/crypto/useIdleKeyTimeout.d.ts +10 -0
  734. package/dist/lib/crypto/useIdleKeyTimeout.js +163 -0
  735. package/dist/lib/crypto/verificationSeal.d.ts +56 -0
  736. package/dist/lib/crypto/verificationSeal.js +220 -0
  737. package/dist/lib/mail/compose/composeQuoting.d.ts +88 -0
  738. package/dist/lib/mail/compose/composeQuoting.js +204 -0
  739. package/dist/lib/mail/compose/emojiData.d.ts +9 -0
  740. package/dist/lib/mail/compose/emojiData.js +18 -0
  741. package/dist/lib/mail/compose/giphyApi.d.ts +17 -0
  742. package/dist/lib/mail/compose/giphyApi.js +20 -0
  743. package/dist/lib/mail/conversationsApi.d.ts +80 -0
  744. package/dist/lib/mail/conversationsApi.js +44 -0
  745. package/dist/lib/mail/dataExportApi.d.ts +50 -0
  746. package/dist/lib/mail/dataExportApi.js +40 -0
  747. package/dist/lib/mail/directoryApi.d.ts +49 -0
  748. package/dist/lib/mail/directoryApi.js +101 -0
  749. package/dist/lib/mail/erasureRequestApi.d.ts +45 -0
  750. package/dist/lib/mail/erasureRequestApi.js +43 -0
  751. package/dist/lib/mail/flaggedMessages.d.ts +22 -0
  752. package/dist/lib/mail/flaggedMessages.js +73 -0
  753. package/dist/lib/mail/focusedInboxOverridesApi.d.ts +37 -0
  754. package/dist/lib/mail/focusedInboxOverridesApi.js +34 -0
  755. package/dist/lib/mail/labelsApi.d.ts +47 -0
  756. package/dist/lib/mail/labelsApi.js +38 -0
  757. package/dist/lib/mail/mailAddress.d.ts +27 -0
  758. package/dist/lib/mail/mailAddress.js +54 -0
  759. package/dist/lib/mail/mailApi.d.ts +850 -0
  760. package/dist/lib/mail/mailApi.js +602 -0
  761. package/dist/lib/mail/mailDetailHooks.d.ts +10 -0
  762. package/dist/lib/mail/mailDetailHooks.js +53 -0
  763. package/dist/lib/mail/mailFilterRulesApi.d.ts +76 -0
  764. package/dist/lib/mail/mailFilterRulesApi.js +45 -0
  765. package/dist/lib/mail/mailSignaturesApi.d.ts +49 -0
  766. package/dist/lib/mail/mailSignaturesApi.js +42 -0
  767. package/dist/lib/mail/mailboxAccessApi.d.ts +74 -0
  768. package/dist/lib/mail/mailboxAccessApi.js +56 -0
  769. package/dist/lib/mail/mailboxImportApi.d.ts +53 -0
  770. package/dist/lib/mail/mailboxImportApi.js +51 -0
  771. package/dist/lib/mail/messageBodySanitizer.d.ts +16 -0
  772. package/dist/lib/mail/messageBodySanitizer.js +118 -0
  773. package/dist/lib/mail/pushClient.d.ts +106 -0
  774. package/dist/lib/mail/pushClient.js +317 -0
  775. package/dist/lib/mail/sendEvents.d.ts +33 -0
  776. package/dist/lib/mail/sendEvents.js +44 -0
  777. package/dist/lib/mail/sendFailure.d.ts +16 -0
  778. package/dist/lib/mail/sendFailure.js +86 -0
  779. package/dist/lib/mail/senderListsApi.d.ts +69 -0
  780. package/dist/lib/mail/senderListsApi.js +126 -0
  781. package/dist/lib/search/queryGrammar.d.ts +51 -0
  782. package/dist/lib/search/queryGrammar.js +111 -0
  783. package/dist/lib/search/searchApi.d.ts +100 -0
  784. package/dist/lib/search/searchApi.js +107 -0
  785. package/dist/lib/search/searchScoring.d.ts +34 -0
  786. package/dist/lib/search/searchScoring.js +44 -0
  787. package/dist/lib/search/searchTier3.d.ts +64 -0
  788. package/dist/lib/search/searchTier3.js +335 -0
  789. package/dist/lib/tasks/tasksApi.d.ts +85 -0
  790. package/dist/lib/tasks/tasksApi.js +55 -0
  791. package/dist/lib/util/api.d.ts +160 -0
  792. package/dist/lib/util/api.js +251 -0
  793. package/dist/lib/util/apiClientContext.d.ts +7 -0
  794. package/dist/lib/util/apiClientContext.js +32 -0
  795. package/dist/lib/util/apiQuery.d.ts +32 -0
  796. package/dist/lib/util/apiQuery.js +42 -0
  797. package/dist/lib/util/clipboard.d.ts +7 -0
  798. package/dist/lib/util/clipboard.js +56 -0
  799. package/dist/lib/util/dateInput.d.ts +6 -0
  800. package/dist/lib/util/dateInput.js +14 -0
  801. package/dist/lib/util/timeZone.d.ts +12 -0
  802. package/dist/lib/util/timeZone.js +32 -0
  803. package/dist/lib/util/useCopyToClipboard.d.ts +12 -0
  804. package/dist/lib/util/useCopyToClipboard.js +34 -0
  805. package/dist/lib/util/useIsMobile.d.ts +10 -0
  806. package/dist/lib/util/useIsMobile.js +29 -0
  807. package/dist/lib/videoconf/videoMeetingsApi.d.ts +116 -0
  808. package/dist/lib/videoconf/videoMeetingsApi.js +49 -0
  809. package/lib/admin/auditLogApi.ts +48 -0
  810. package/lib/admin/distributionListsApi.ts +77 -0
  811. package/lib/admin/domainsApi.ts +113 -0
  812. package/lib/admin/escrowAccessRequestsApi.ts +110 -0
  813. package/lib/admin/escrowAuditLogApi.ts +101 -0
  814. package/lib/admin/escrowScopesApi.ts +112 -0
  815. package/lib/admin/leftoverMailboxApi.ts +120 -0
  816. package/lib/admin/mailboxPolicyApi.ts +38 -0
  817. package/lib/admin/matterExportApi.ts +62 -0
  818. package/lib/admin/matterSearchApi.ts +35 -0
  819. package/lib/admin/mattersApi.ts +86 -0
  820. package/lib/admin/pluginsApi.ts +339 -0
  821. package/lib/admin/retentionPolicyApi.ts +46 -0
  822. package/lib/admin/setupApi.ts +40 -0
  823. package/lib/admin/transportRulesApi.ts +106 -0
  824. package/lib/appearance/preferencesApi.ts +335 -0
  825. package/lib/auth/profileApi.ts +77 -0
  826. package/lib/auth/session.ts +238 -0
  827. package/lib/branding/brandingApi.ts +97 -0
  828. package/lib/branding/useBranding.ts +81 -0
  829. package/lib/calendar/calendarApi.ts +309 -0
  830. package/lib/calendar/calendarColors.ts +45 -0
  831. package/lib/calendar/calendarDragIds.ts +112 -0
  832. package/lib/calendar/calendarMutations.ts +236 -0
  833. package/lib/calendar/eventDescription.ts +211 -0
  834. package/lib/calendar/freeBusyApi.ts +197 -0
  835. package/lib/calendar/inviteApi.ts +154 -0
  836. package/lib/calendar/recurrence.ts +285 -0
  837. package/lib/components/avatar/ContactAvatar.tsx +47 -0
  838. package/lib/components/buttons/Button.tsx +40 -0
  839. package/lib/components/buttons/CopyButton.tsx +45 -0
  840. package/lib/components/feedback/Alert.tsx +13 -0
  841. package/lib/components/feedback/Skeleton.tsx +38 -0
  842. package/lib/components/forms/FormField.tsx +23 -0
  843. package/lib/components/navigation/BottomTabBar.tsx +66 -0
  844. package/lib/components/overlays/Drawer.tsx +72 -0
  845. package/lib/components/overlays/Modal.tsx +64 -0
  846. package/lib/components/overlays/PopoverPortal.tsx +74 -0
  847. package/lib/components/overlays/overlayStack.ts +165 -0
  848. package/lib/components/pickers/MiniDatePicker.tsx +90 -0
  849. package/lib/contacts/contactsApi.ts +289 -0
  850. package/lib/contacts/vcard.ts +197 -0
  851. package/lib/crypto/composeSecurity.ts +140 -0
  852. package/lib/crypto/encoding.ts +36 -0
  853. package/lib/crypto/escrowKeys.ts +74 -0
  854. package/lib/crypto/idleTimeout.ts +49 -0
  855. package/lib/crypto/keySession.ts +483 -0
  856. package/lib/crypto/keys.ts +105 -0
  857. package/lib/crypto/keyvaultApi.ts +674 -0
  858. package/lib/crypto/masterKey.ts +134 -0
  859. package/lib/crypto/masterKeyWraps.ts +269 -0
  860. package/lib/crypto/messageSecurity.ts +600 -0
  861. package/lib/crypto/mime.ts +568 -0
  862. package/lib/crypto/passkeyUnlock.ts +103 -0
  863. package/lib/crypto/passwordUnlock.ts +98 -0
  864. package/lib/crypto/recoveryCode.ts +93 -0
  865. package/lib/crypto/signingProviderApi.ts +135 -0
  866. package/lib/crypto/smime.ts +459 -0
  867. package/lib/crypto/smimeMessage.ts +491 -0
  868. package/lib/crypto/useIdleKeyTimeout.ts +176 -0
  869. package/lib/crypto/verificationSeal.ts +288 -0
  870. package/lib/mail/compose/composeQuoting.ts +243 -0
  871. package/lib/mail/compose/emojiData.ts +34 -0
  872. package/lib/mail/compose/giphyApi.ts +31 -0
  873. package/lib/mail/conversationsApi.ts +123 -0
  874. package/lib/mail/dataExportApi.ts +73 -0
  875. package/lib/mail/directoryApi.ts +161 -0
  876. package/lib/mail/erasureRequestApi.ts +71 -0
  877. package/lib/mail/flaggedMessages.ts +80 -0
  878. package/lib/mail/focusedInboxOverridesApi.ts +64 -0
  879. package/lib/mail/labelsApi.ts +71 -0
  880. package/lib/mail/mailAddress.ts +76 -0
  881. package/lib/mail/mailApi.ts +1286 -0
  882. package/lib/mail/mailDetailHooks.ts +57 -0
  883. package/lib/mail/mailFilterRulesApi.ts +116 -0
  884. package/lib/mail/mailSignaturesApi.ts +84 -0
  885. package/lib/mail/mailboxAccessApi.ts +106 -0
  886. package/lib/mail/mailboxImportApi.ts +87 -0
  887. package/lib/mail/messageBodySanitizer.ts +129 -0
  888. package/lib/mail/pushClient.ts +375 -0
  889. package/lib/mail/sendEvents.ts +72 -0
  890. package/lib/mail/sendFailure.ts +98 -0
  891. package/lib/mail/senderListsApi.ts +161 -0
  892. package/lib/search/queryGrammar.ts +179 -0
  893. package/lib/search/searchApi.ts +199 -0
  894. package/lib/search/searchScoring.ts +46 -0
  895. package/lib/search/searchTier3.ts +406 -0
  896. package/lib/tasks/tasksApi.ts +128 -0
  897. package/lib/util/api.ts +318 -0
  898. package/lib/util/apiClientContext.ts +35 -0
  899. package/lib/util/apiQuery.ts +61 -0
  900. package/lib/util/clipboard.ts +55 -0
  901. package/lib/util/dateInput.ts +15 -0
  902. package/lib/util/timeZone.ts +33 -0
  903. package/lib/util/useCopyToClipboard.ts +48 -0
  904. package/lib/util/useIsMobile.ts +34 -0
  905. package/lib/videoconf/videoMeetingsApi.ts +144 -0
  906. package/package.json +10 -4
@@ -0,0 +1,318 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+ /**
6
+ * Minimal client-side helper shared by every app in this project: a `fetch` wrapper that talks to the
7
+ * same-origin RapidMX API. There is no client router or HTTP client shipped by `@rapidrest/react`, so this
8
+ * is deliberately small and framework-free.
9
+ *
10
+ * This service never issues its own JWTs — identity comes entirely from a separate `auth-server` deployment
11
+ * (see `.claude/NOTES.md`). Authentication rides along via the `jwt` HttpOnly cookie that auth-server sets on
12
+ * sign-in — the browser attaches it automatically to every same-origin `fetch()` call (the default
13
+ * `credentials: "same-origin"` mode), and this server's `JWTStrategy` accepts it as a credential for every
14
+ * authenticated request, not just SSR page loads. There is no local elevation/step-up flow here (unlike
15
+ * auth-server's own `api.ts`, which this is a trimmed sibling of): a request to an elevation-gated endpoint
16
+ * (`@RequiresElevation()` on the server) made with a non-elevated token fails with an `ApiRequestError` of
17
+ * status 403 and code `"api-104"`, and it is up to the caller to send the browser to auth-server's
18
+ * `/auth/elevate?return_to=...` page, which returns it to `return_to` once the user has confirmed their identity
19
+ * (the admin console does exactly that - see `AdminShell` in `@rapidmx/web-client`). Code `"api-103"` is a
20
+ * different 403 - the caller lacks a required role, and elevating won't help.
21
+ */
22
+
23
+ export class ApiRequestError extends Error {
24
+ status: number;
25
+ code?: string;
26
+ /**
27
+ * The response's whole parsed JSON body, for an endpoint that says more than `message` - e.g. a failed send's
28
+ * per-recipient SMTP results under `details`. `undefined` when the response had no JSON body (or the error
29
+ * was raised on the client), so a caller must treat it as untyped, untrusted data and read it defensively.
30
+ */
31
+ details?: unknown;
32
+
33
+ constructor(message: string, status: number, code?: string, details?: unknown) {
34
+ super(message);
35
+ this.name = "ApiRequestError";
36
+ this.status = status;
37
+ this.code = code;
38
+ this.details = details;
39
+ }
40
+ }
41
+
42
+ /**
43
+ * Absolute origin `apiFetch()` targets instead of a same-origin relative path - unset (`""`, the
44
+ * default) everywhere this library has run until now (the SSR web/admin apps, always served from the
45
+ * same origin as the API they call). Set once via `configureApiBaseUrl()` by a consumer that genuinely
46
+ * runs on a *different* origin than the API - e.g. the Electron desktop client, whose renderer has no
47
+ * "same origin as the server" to rely on the way a browser tab loaded from that server does.
48
+ */
49
+ let apiBaseUrl = "";
50
+
51
+ /**
52
+ * Points `apiFetch()` at `baseUrl` (e.g. `"https://mail.example.com"`) instead of the default
53
+ * same-origin relative path. Only needed by a consumer whose own origin genuinely differs from the
54
+ * RapidMX server's - see `apiBaseUrl`'s own doc comment. Requires that server's `cors:origins` config
55
+ * include this consumer's own origin (see `@rapidrest/service-core`'s `Server.js` CORS middleware,
56
+ * which only reflects `access-control-allow-credentials` for an explicitly allow-listed origin - the
57
+ * default "allow every origin" behavior when `cors:origins` is unset does NOT carry credentials) and
58
+ * that whatever sets the `jwt` cookie issues it with `SameSite=None; Secure` - a same-origin deployment
59
+ * never needed either, and this function alone does not make a cross-origin deployment secure or
60
+ * functional on its own.
61
+ */
62
+ export function configureApiBaseUrl(baseUrl: string): void {
63
+ apiBaseUrl = baseUrl.replace(/\/$/, "");
64
+ }
65
+
66
+ /**
67
+ * The origin `configureApiBaseUrl()` set - `""` (same origin) when it never was. For a caller that talks to the
68
+ * RapidMX server some way `apiFetch()` can't, such as the push WebSocket, which must go to the same origin.
69
+ */
70
+ export function apiOrigin(): string {
71
+ return apiBaseUrl;
72
+ }
73
+
74
+ /**
75
+ * The full URL for an `@ApiRoute`-declared `path` (e.g. `/mail/attachments/a1/content`) - the `/api`
76
+ * prefix plus whatever origin `configureApiBaseUrl()` set (a same-origin relative `/api/...` path when
77
+ * it was never called). Every call site that can't go through `apiFetch()` - a raw-bytes upload, a
78
+ * non-JSON download, or a plain URL handed to an `<a href>`/`<img src>` - must build its URL here rather
79
+ * than hard-coding `/api...`, or it silently ignores a configured cross-origin base URL. A raw `fetch()`
80
+ * built on this should also pass `credentials: "include"` so a cross-origin call still carries the `jwt`
81
+ * cookie (harmless for a same-origin one).
82
+ */
83
+ export function apiUrl(path: string): string {
84
+ return `${apiBaseUrl}/api${path}`;
85
+ }
86
+
87
+ /**
88
+ * Mirrors `@rapidrest/service-core`'s `DEFAULT_CSRF_COOKIE_NAME`/`DEFAULT_CSRF_HEADER_NAME` — kept as
89
+ * local literals since this package has no dependency on that one.
90
+ */
91
+ const CSRF_COOKIE_NAME = "csrf";
92
+ const CSRF_HEADER_NAME = "x-csrf-token";
93
+ const CSRF_SAFE_METHODS = new Set(["GET", "HEAD", "OPTIONS"]);
94
+
95
+ /**
96
+ * Reads the CSRF double-submit cookie a `jwt`-cookie-issuing server sets (see `@rapidrest/auth`'s
97
+ * `CsrfUtils`) directly off `document.cookie`. That cookie is deliberately host-only and non-`HttpOnly`
98
+ * — see `@rapidrest/service-core`'s `src/http/csrf/csrf.ts` for the full rationale, in particular why a
99
+ * *cross-origin* call (`authApiFetch()` below) can never find one here: a cookie set by auth-server's
100
+ * host is never present in this app's own `document.cookie`, by design — that's what makes the cookie
101
+ * host-only in the first place, and it's why `authApiFetch()`'s CSRF protection has to come from the
102
+ * server checking its Origin allow-list instead (see its own doc comment).
103
+ */
104
+ function readCsrfCookie(): string | undefined {
105
+ if (typeof document === "undefined") {
106
+ return undefined;
107
+ }
108
+ for (const part of document.cookie.split("; ")) {
109
+ const idx = part.indexOf("=");
110
+ if (idx > 0 && part.slice(0, idx) === CSRF_COOKIE_NAME) {
111
+ return part.slice(idx + 1);
112
+ }
113
+ }
114
+ return undefined;
115
+ }
116
+
117
+ /**
118
+ * Echoes the CSRF double-submit cookie back as a header on `headers`, for a mutating request that doesn't
119
+ * already carry one — the browser-side half of the double-submit check `@rapidrest/service-core`'s
120
+ * `RouteUtils.checkCsrf()` enforces server-side. A safe method, a caller-supplied header already present,
121
+ * or simply no cookie yet (e.g. this page's very first request) all leave `headers` untouched — the
122
+ * server itself never requires this for any of those cases.
123
+ */
124
+ function applyCsrfHeader(headers: Headers, method: string | undefined): void {
125
+ const m = (method ?? "GET").toUpperCase();
126
+ if (CSRF_SAFE_METHODS.has(m) || headers.has(CSRF_HEADER_NAME)) {
127
+ return;
128
+ }
129
+ const token = readCsrfCookie();
130
+ if (token) {
131
+ headers.set(CSRF_HEADER_NAME, token);
132
+ }
133
+ }
134
+
135
+ /**
136
+ * `headers` as a `Headers` with the CSRF double-submit header added, for a mutating request that is built without `apiFetch()` - an upload of a
137
+ * file's own bytes, which cannot go through `apiFetch()` because that always sends JSON. Without it the server refuses the request as "missing a valid
138
+ * CSRF token". `method` defaults to `POST`; a safe method or no cookie leaves the headers as they were, exactly as `apiFetch()` does.
139
+ */
140
+ export function withCsrfHeader(headers: Record<string, string>, method: string = "POST"): Headers {
141
+ const result = new Headers(headers);
142
+ applyCsrfHeader(result, method);
143
+ return result;
144
+ }
145
+
146
+ /**
147
+ * `fetch()` against the RapidMX server's API - same-origin unless `configureApiBaseUrl()` has been
148
+ * called, in which case this also switches to `credentials: "include"` so the configured cross-origin
149
+ * call still carries the `jwt` cookie (a plain relative fetch never needs this - `credentials:
150
+ * "same-origin"`, fetch's own default, already attaches it). `path` is the route as declared by
151
+ * `@ApiRoute` (e.g. `/mail/mailboxes`) — the `/api` prefix that decorator always adds is applied here,
152
+ * in one place, rather than repeated at every call site.
153
+ */
154
+ export async function apiFetch<T = unknown>(path: string, init: RequestInit = {}): Promise<T> {
155
+ const headers = new Headers(init.headers);
156
+ headers.set("Content-Type", "application/json");
157
+ applyCsrfHeader(headers, init.method);
158
+ const credentials = apiBaseUrl ? "include" : init.credentials;
159
+
160
+ const res = await fetch(apiUrl(path), { ...init, headers, credentials });
161
+ return decodeApiResponse<T>(res, (error) => unauthorizedObserver?.(error));
162
+ }
163
+
164
+ /**
165
+ * `fetch()` against auth-server's API — a *different* origin than this app, unlike `apiFetch()` above. Used
166
+ * only for the handful of actions that must be issued by auth-server itself (e.g. admin impersonation, which
167
+ * needs to mint a token with the target user's real roles/scopes the way auth-server's own sign-in does —
168
+ * see `.claude/NOTES.md`).
169
+ *
170
+ * Requires `credentials: "include"` so the browser both attaches this app's own `jwt` cookie to the request
171
+ * and accepts whatever `Set-Cookie` auth-server's response carries back. This only actually works when
172
+ * auth-server and this app are deployed under a shared parent cookie domain (e.g. `Domain=.example.com`) —
173
+ * a deployment-level requirement owned by auth-server/the Helm chart, not configured here — and auth-server's
174
+ * CORS config must explicitly allow this app's origin with credentials.
175
+ *
176
+ * `applyCsrfHeader()` is still called here for consistency, but it never actually finds a token for a truly
177
+ * cross-origin call — see its own doc comment on `readCsrfCookie()` for why that's correct rather than a
178
+ * gap: auth-server's CSRF protection for this call shape comes from its own Origin allow-list check, not a
179
+ * double-submit cookie this app's JavaScript could never read in the first place.
180
+ */
181
+ export async function authApiFetch<T = unknown>(authServerUrl: string, path: string, init: RequestInit = {}): Promise<T> {
182
+ const headers = new Headers(init.headers);
183
+ headers.set("Content-Type", "application/json");
184
+ applyCsrfHeader(headers, init.method);
185
+
186
+ const res = await fetch(`${authServerUrl}/api${path}`, { ...init, headers, credentials: "include" });
187
+ return decodeApiResponse<T>(res);
188
+ }
189
+
190
+ let unauthorizedObserver: ((error: ApiRequestError) => void) | undefined;
191
+
192
+ /**
193
+ * Registers the one function that hears about every `401` this server's API (`apiFetch()`, not auth-server's) answers - the
194
+ * signed-in session has ended or expired. It only observes: the request still rejects with the same `ApiRequestError`, so
195
+ * a caller's own handling is unchanged. The app frame uses it to say "Your session expired" once, whichever request noticed
196
+ * first (a background refresh included). Pass `undefined` to remove it. A throwing observer never affects the request.
197
+ */
198
+ export function setApiUnauthorizedObserver(observer: ((error: ApiRequestError) => void) | undefined): void {
199
+ unauthorizedObserver = observer;
200
+ }
201
+
202
+ /**
203
+ * `onUnauthorized`, when given, is invoked (never awaited) for a `401` response only - `apiFetch()` passes one
204
+ * that forwards to whatever `setApiUnauthorizedObserver()` last registered; `authApiFetch()` and a plain
205
+ * `createApiClient()`-made client's `fetch()` (which forwards to that instance's own
206
+ * `setUnauthorizedObserver()`) pass their own. A throwing `onUnauthorized` never changes what the caller sees.
207
+ */
208
+ async function decodeApiResponse<T>(res: Response, onUnauthorized?: (error: ApiRequestError) => void): Promise<T> {
209
+ const contentType = res.headers.get("content-type") ?? "";
210
+ const body = contentType.includes("application/json") ? await res.json().catch(() => undefined) : undefined;
211
+
212
+ if (!res.ok) {
213
+ const message = (body && (body.message || body.error)) || res.statusText || "Request failed.";
214
+ const error = new ApiRequestError(message, res.status, body?.code, body);
215
+ if (res.status === 401 && onUnauthorized) {
216
+ try {
217
+ onUnauthorized(error);
218
+ } catch {
219
+ // An observer's failure must not change what the caller sees.
220
+ }
221
+ }
222
+ throw error;
223
+ }
224
+
225
+ return body as T;
226
+ }
227
+
228
+ /**
229
+ * The low-level shape both the default global client (`apiFetch()`, driven by `configureApiBaseUrl()` and the
230
+ * `jwt` cookie) and an explicit `createApiClient()` instance expose - so a `mailApi.ts`-style module can be
231
+ * written once against this interface and used from either. There is deliberately no `authFetch`/cross-origin
232
+ * counterpart here: `authApiFetch()`'s `authServerUrl` is already explicit per call, so it doesn't need this
233
+ * abstraction the way the single implicit `apiBaseUrl` global does.
234
+ */
235
+ export interface ApiClient {
236
+ /** Same contract as `apiFetch()`: prefixes `path` with `/api`, parses a JSON response, and rejects with
237
+ * `ApiRequestError` on a non-ok response. */
238
+ fetch<T = unknown>(path: string, init?: RequestInit): Promise<T>;
239
+ /**
240
+ * This client instance's own `setApiUnauthorizedObserver()` equivalent - see `createApiClient()`'s doc
241
+ * comment for why it is per-instance rather than shared with the module-level `setApiUnauthorizedObserver()`
242
+ * (or across other `ApiClient` instances).
243
+ */
244
+ setUnauthorizedObserver(observer: ((error: ApiRequestError) => void) | undefined): void;
245
+ }
246
+
247
+ /** `createApiClient()`'s options. */
248
+ export interface CreateApiClientOptions {
249
+ /** This client's origin, e.g. `"https://mail.example.com"` - always used, never the global
250
+ * `configureApiBaseUrl()` value. A trailing slash is stripped, matching `configureApiBaseUrl()`. */
251
+ baseUrl: string;
252
+ /**
253
+ * Called fresh before every single request this client makes - never cached or reused across calls, so a
254
+ * caller can transparently rotate/refresh the underlying session token between requests (e.g. a
255
+ * background refresh keyed on this one account) without this client needing to know anything about
256
+ * refresh logic itself. Its resolved value is sent as `Authorization: jwt <token>` - the same header
257
+ * format `JWTStrategy` already accepts server-side alongside the `jwt` cookie - never `credentials:
258
+ * "include"`, since a native multi-account app has no relevant cookie jar for a given account's origin.
259
+ * A rejection here rejects the request itself (the underlying `fetch()` is never called).
260
+ */
261
+ getAccessToken: () => Promise<string>;
262
+ }
263
+
264
+ /**
265
+ * Builds an explicit-context `ApiClient`: everything `apiFetch()` does, but always against `baseUrl` (never
266
+ * the `configureApiBaseUrl()` global) and always authenticated with a bearer token from `getAccessToken()`
267
+ * (never the `jwt` cookie / `credentials: "include"`). ADDITIVE to the existing global-config mode -
268
+ * `apiFetch()`/`authApiFetch()`/`configureApiBaseUrl()` are untouched and keep working exactly as before for
269
+ * every existing caller; this is for a consumer (the Tauri multi-account client) that needs several fully
270
+ * independent origin/session contexts open at once, which the single module-level `apiBaseUrl` global can't
271
+ * represent.
272
+ *
273
+ * Distinct instances never share state: each closes over its own `baseUrl`, `getAccessToken` and unauthorized
274
+ * observer, so two accounts' clients never cross-talk even when both are live in the same process.
275
+ *
276
+ * **401 handling is per-instance, not global.** The existing `setApiUnauthorizedObserver()` is one process-wide
277
+ * "you're signed out" signal, correct for a single-session app (one browser tab, one Electron window - there is
278
+ * only ever one session to lose). A multi-account app has no single account whose 401 means "the app" is
279
+ * unauthorized, so an `ApiClient` from `createApiClient()` does NOT invoke the global observer at all; instead
280
+ * each instance has its own `setUnauthorizedObserver()` a caller can register per account (e.g. to mark that
281
+ * one account's tab as needing re-authentication without touching the others).
282
+ */
283
+ export function createApiClient(options: CreateApiClientOptions): ApiClient {
284
+ const baseUrl = options.baseUrl.replace(/\/$/, "");
285
+ const { getAccessToken } = options;
286
+ let unauthorizedObserver: ((error: ApiRequestError) => void) | undefined;
287
+
288
+ async function clientFetch<T = unknown>(path: string, init: RequestInit = {}): Promise<T> {
289
+ const headers = new Headers(init.headers);
290
+ headers.set("Content-Type", "application/json");
291
+ const token = await getAccessToken();
292
+ headers.set("Authorization", `jwt ${token}`);
293
+
294
+ const res = await fetch(`${baseUrl}/api${path}`, { ...init, headers });
295
+ return decodeApiResponse<T>(res, (error) => unauthorizedObserver?.(error));
296
+ }
297
+
298
+ return {
299
+ fetch: clientFetch,
300
+ setUnauthorizedObserver(observer) {
301
+ unauthorizedObserver = observer;
302
+ },
303
+ };
304
+ }
305
+
306
+ /**
307
+ * Routes a request to `client.fetch()` when `client` is given, else to the default global `apiFetch()` - the
308
+ * one call every REST client module (`mailApi.ts` etc.) uses to add optional explicit-`ApiClient` support to
309
+ * each of its exported functions with minimal churn: give the function a trailing `client?: ApiClient`
310
+ * parameter (so every existing call site, which never passes one, is unaffected - `undefined` here means
311
+ * exactly what calling `apiFetch()` directly always meant), and swap its `apiFetch(...)` call for
312
+ * `withClient(client, ...)`. A function that calls another exported function of the same module internally
313
+ * (e.g. `mailApi.ts`'s `grantMailboxAccess()` calling `getMailboxAcl()`) threads its own `client` through
314
+ * that call too, so a whole call chain stays pinned to one account.
315
+ */
316
+ export function withClient<T = unknown>(client: ApiClient | undefined, path: string, init?: RequestInit): Promise<T> {
317
+ return client ? client.fetch<T>(path, init) : apiFetch<T>(path, init);
318
+ }
@@ -0,0 +1,35 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+ /**
6
+ * Lets a deeply-nested component reach "the active account's `ApiClient`" without prop-drilling it through
7
+ * every layer in between — the missing piece `createApiClient()` (see `api.ts`) left open: that function
8
+ * gives a host app (e.g. the native, multi-account `tauri-client`) a way to *build* a per-account client, but
9
+ * nothing let a component *read* one back out short of threading it through every prop list by hand.
10
+ *
11
+ * Same shape as `overlays/overlayStack.ts`'s `OverlayDepthContext` — a bare `createContext()` plus a `useX()`
12
+ * reader, no dedicated `<Provider>` wrapper component, so a host app wraps its tree in `ApiClientContext.Provider`
13
+ * directly (e.g. `<ApiClientContext.Provider value={client}>{children}</ApiClientContext.Provider>`) exactly the
14
+ * way `Modal.tsx`/`Drawer.tsx` already do for `OverlayDepthContext`.
15
+ *
16
+ * The default value is `undefined`, meaning "no override" — every existing consumer (the SSR web/admin apps,
17
+ * the Electron client) renders with no `ApiClientContext.Provider` anywhere above it, so `useApiClient()` there
18
+ * always returns `undefined`, which is exactly what every converted REST function's own `client?: ApiClient`
19
+ * parameter already treats as "use the default global cookie-based `apiFetch()` path" (see `withClient()`'s doc
20
+ * comment in `api.ts`). A component under a `tauri-client`-style provider instead gets that account's own
21
+ * `ApiClient` back, and can pass it straight through as the trailing `client` argument of any converted
22
+ * function with no adapter needed: `const client = useApiClient(); await listMessages(params, client);`.
23
+ */
24
+ import { createContext, useContext } from "react";
25
+ import { ApiClient } from "./api.js";
26
+
27
+ /** The active account's `ApiClient`, or `undefined` when nothing above the caller provided one — see this
28
+ * file's own doc comment. */
29
+ export const ApiClientContext = createContext<ApiClient | undefined>(undefined);
30
+
31
+ /** The nearest `ApiClientContext.Provider`'s value, or `undefined` when there is none — the same `client`
32
+ * every converted REST function's own optional trailing parameter accepts. */
33
+ export function useApiClient(): ApiClient | undefined {
34
+ return useContext(ApiClientContext);
35
+ }
@@ -0,0 +1,61 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+ /**
6
+ * The pagination query-string convention shared by every `*Api.ts` wrapper (`mailApi.ts`,
7
+ * `contactsApi.ts`, `tasksApi.ts`, `calendarApi.ts`) — split out of `mailApi.ts` once more than one of
8
+ * them needed it, rather than each reimplementing it or importing it from `mailApi.ts` for no reason
9
+ * other than it happening to live there first.
10
+ */
11
+
12
+ export interface ListParams {
13
+ page?: number;
14
+ limit?: number;
15
+ }
16
+
17
+ const DEFAULT_PAGE_SIZE = 25;
18
+
19
+ /**
20
+ * Builds a `limit`/`page` query string, plus any extra scope/filter params (e.g. `folderUid`,
21
+ * or one of `@rapidmx/restapi`'s generic query-operator values like `startDate=lte(...)`).
22
+ */
23
+ export function buildQuery(params: ListParams, extra: Record<string, string> = {}): string {
24
+ const parts: string[] = [`limit=${params.limit ?? DEFAULT_PAGE_SIZE}`, `page=${params.page ?? 0}`];
25
+ for (const [key, value] of Object.entries(extra)) {
26
+ parts.push(`${key}=${encodeURIComponent(value)}`);
27
+ }
28
+ return parts.join("&");
29
+ }
30
+
31
+ /**
32
+ * Optional paging/scope params for the async-request list endpoints (`listExportRequests()`,
33
+ * `listImportRequests()`, `listErasureRequests()`, `listMatterExportRequests()`,
34
+ * `listAccessRequests()`). Server contract: newest first, `limit` capped at 500, `page` zero-based,
35
+ * `matterId` honored only by the Matter-scoped (escrow) endpoints.
36
+ */
37
+ export interface RequestListParams extends ListParams {
38
+ /** Restricts the list to one Matter - only meaningful for Matter-scoped request lists. */
39
+ matterId?: string;
40
+ }
41
+
42
+ /**
43
+ * Builds a `?limit=&page=&matterId=` suffix from only the params actually supplied - unlike
44
+ * `buildQuery()`, applies no default page size (these endpoints historically returned every request
45
+ * with no params at all, so a caller passing nothing keeps that exact request). Returns `""` when no
46
+ * param is set.
47
+ */
48
+ export function buildRequestListQuery(params: RequestListParams = {}): string {
49
+ const query = new URLSearchParams();
50
+ if (params.limit !== undefined) {
51
+ query.set("limit", String(params.limit));
52
+ }
53
+ if (params.page !== undefined) {
54
+ query.set("page", String(params.page));
55
+ }
56
+ if (params.matterId) {
57
+ query.set("matterId", params.matterId);
58
+ }
59
+ const encoded = query.toString();
60
+ return encoded ? `?${encoded}` : "";
61
+ }
@@ -0,0 +1,55 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+
6
+ /**
7
+ * The legacy copy path: selects `text` in an off-screen, read-only `<textarea>` and runs
8
+ * `document.execCommand("copy")`. Used where the async Clipboard API is missing (an insecure `http:` origin,
9
+ * an older browser) or refuses (permission denied, the document isn't focused). Puts focus back where it was,
10
+ * since selecting the textarea moves it. `false` when there is no DOM or the browser declines the command.
11
+ */
12
+ function copyWithExecCommand(text: string): boolean {
13
+ if (typeof document === "undefined") {
14
+ return false;
15
+ }
16
+ const previouslyFocused = document.activeElement;
17
+ const textarea = document.createElement("textarea");
18
+ textarea.value = text;
19
+ textarea.setAttribute("readonly", "");
20
+ textarea.setAttribute("aria-hidden", "true");
21
+ textarea.style.cssText = "position:fixed;top:0;left:0;width:1px;height:1px;padding:0;border:0;opacity:0;pointer-events:none";
22
+ document.body.appendChild(textarea);
23
+ let copied = false;
24
+ try {
25
+ textarea.select();
26
+ textarea.setSelectionRange(0, text.length);
27
+ copied = typeof document.execCommand === "function" && document.execCommand("copy");
28
+ } catch {
29
+ copied = false;
30
+ } finally {
31
+ textarea.remove();
32
+ if (previouslyFocused instanceof HTMLElement) {
33
+ previouslyFocused.focus();
34
+ }
35
+ }
36
+ return copied;
37
+ }
38
+
39
+ /**
40
+ * Copies `text` to the system clipboard and reports whether it worked - never rejects, so a caller can
41
+ * simply show "Copied" or "Couldn't copy". Tries `navigator.clipboard.writeText()` first and, when that is
42
+ * unavailable or rejects, the hidden-textarea `execCommand("copy")` fallback. Must run from a user gesture
43
+ * (a click handler) for either route to be allowed.
44
+ */
45
+ export async function copyTextToClipboard(text: string): Promise<boolean> {
46
+ try {
47
+ if (typeof navigator !== "undefined" && typeof navigator.clipboard?.writeText === "function") {
48
+ await navigator.clipboard.writeText(text);
49
+ return true;
50
+ }
51
+ } catch {
52
+ // Denied or unavailable right now - the legacy path below may still succeed.
53
+ }
54
+ return copyWithExecCommand(text);
55
+ }
@@ -0,0 +1,15 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+ /** Shared by every form with a `<input type="datetime-local">` bound to a server-side ISO instant
6
+ * (originally `EventModal.tsx`'s own private helper, split out once the Settings Auto-Reply page needed
7
+ * the identical conversion — same "extract once a second consumer needs it" precedent as `apiQuery.ts`). */
8
+
9
+ /** `<input type="datetime-local">` reads/writes local time with no timezone suffix — `new Date(str)`
10
+ * parses that as the browser's own local time, matching what the picker visually showed the user. */
11
+ export function toDatetimeLocal(iso: string): string {
12
+ const d = new Date(iso);
13
+ const local = new Date(d.getTime() - d.getTimezoneOffset() * 60_000);
14
+ return local.toISOString().slice(0, 16);
15
+ }
@@ -0,0 +1,33 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+
6
+ /** The time zone a mailbox has when nothing better is known - the server's own default. */
7
+ export const DEFAULT_TIME_ZONE = "UTC";
8
+
9
+ /**
10
+ * The IANA time zone of the device this is running on (`"America/Los_Angeles"`), as the browser reports it, or `"UTC"` where it
11
+ * can't say (server-side rendering, an old engine). What a new mailbox, and a settings form with nothing chosen yet, start with.
12
+ */
13
+ export function deviceTimeZone(): string {
14
+ try {
15
+ return Intl.DateTimeFormat().resolvedOptions().timeZone || DEFAULT_TIME_ZONE;
16
+ } catch {
17
+ return DEFAULT_TIME_ZONE;
18
+ }
19
+ }
20
+
21
+ /**
22
+ * Every time zone the browser can name, for a picker: `Intl.supportedValuesOf("timeZone")` where there is one (it leaves out `UTC`,
23
+ * which is added), else just `extra` - the zones the caller already holds, such as a mailbox's current one.
24
+ */
25
+ export function timeZoneOptions(...extra: string[]): string[] {
26
+ let zones: string[] = [];
27
+ try {
28
+ zones = (Intl as unknown as { supportedValuesOf?: (key: string) => string[] }).supportedValuesOf?.("timeZone") ?? [];
29
+ } catch {
30
+ zones = [];
31
+ }
32
+ return [...new Set([DEFAULT_TIME_ZONE, ...zones, ...extra.filter(Boolean)])].sort((a, b) => a.localeCompare(b));
33
+ }
@@ -0,0 +1,48 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+ import { useCallback, useEffect, useRef, useState } from "react";
6
+ import { copyTextToClipboard } from "./clipboard.js";
7
+
8
+ /** `"copied"`/`"failed"` are transient - they fall back to `"idle"` after the hook's reset delay. */
9
+ export type CopyStatus = "idle" | "copied" | "failed";
10
+
11
+ /** How long "Copied" stays up by default. */
12
+ export const COPY_FEEDBACK_MS = 2000;
13
+
14
+ /**
15
+ * Copy-to-clipboard with brief feedback state: `copy(text)` (see `copyTextToClipboard()`) sets `status` to
16
+ * `"copied"` or `"failed"` and back to `"idle"` after `resetMs`. Safe to unmount mid-copy or mid-feedback.
17
+ */
18
+ export default function useCopyToClipboard(resetMs: number = COPY_FEEDBACK_MS): {
19
+ status: CopyStatus;
20
+ copy: (text: string) => Promise<boolean>;
21
+ } {
22
+ const [status, setStatus] = useState<CopyStatus>("idle");
23
+ const timer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);
24
+ const mounted = useRef(true);
25
+
26
+ useEffect(() => {
27
+ mounted.current = true;
28
+ return () => {
29
+ mounted.current = false;
30
+ clearTimeout(timer.current);
31
+ };
32
+ }, []);
33
+
34
+ const copy = useCallback(
35
+ async (text: string) => {
36
+ const copied = await copyTextToClipboard(text);
37
+ if (mounted.current) {
38
+ setStatus(copied ? "copied" : "failed");
39
+ clearTimeout(timer.current);
40
+ timer.current = setTimeout(() => setStatus("idle"), resetMs);
41
+ }
42
+ return copied;
43
+ },
44
+ [resetMs],
45
+ );
46
+
47
+ return { status, copy };
48
+ }
@@ -0,0 +1,34 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+ import { useEffect, useState } from "react";
6
+
7
+ /** Matches this app's Tailwind `md` breakpoint, the cutoff used throughout for mobile vs. desktop layout. */
8
+ const DEFAULT_BREAKPOINT_PX = 768;
9
+
10
+ /**
11
+ * `true` below `breakpointPx` (default 768, i.e. Tailwind's `md`). Always `false` during SSR and the
12
+ * initial client render — corrected in an effect after mount, the same "read real client state once
13
+ * mounted" convention already used by `MailShell`'s query-param reads — so server-rendered markup and
14
+ * the first hydrated frame always agree (no hydration-mismatch warning), at the cost of a one-frame
15
+ * desktop-layout flash for mobile visitors on first load. Prefer plain Tailwind `md:` classes for pure
16
+ * layout/visibility; reach for this hook only when a component needs to make an actual JS-level
17
+ * decision (e.g. real navigation vs. local state).
18
+ */
19
+ export default function useIsMobile(breakpointPx: number = DEFAULT_BREAKPOINT_PX): boolean {
20
+ const [isMobile, setIsMobile] = useState(false);
21
+
22
+ useEffect(() => {
23
+ const mql = window.matchMedia(`(max-width: ${breakpointPx - 1}px)`);
24
+ setIsMobile(mql.matches);
25
+
26
+ function handleChange(e: MediaQueryListEvent) {
27
+ setIsMobile(e.matches);
28
+ }
29
+ mql.addEventListener("change", handleChange);
30
+ return () => mql.removeEventListener("change", handleChange);
31
+ }, [breakpointPx]);
32
+
33
+ return isMobile;
34
+ }