@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
@@ -1,423 +1,423 @@
1
- ///////////////////////////////////////////////////////////////////////////////
2
- // Copyright (C) 2026 Jean-Philippe Steinmetz
3
- // SPDX-License-Identifier: MPL-2.0
4
- ///////////////////////////////////////////////////////////////////////////////
5
- import React, { ChangeEvent, FormEvent, useRef, useState } from "react";
6
- import { ApiRequestError } from "@rapidmx/react-shared/util/api.js";
7
- import {
8
- Branding,
9
- deleteBrandingIcon,
10
- deleteBrandingLogo,
11
- deleteBrandingStylesheet,
12
- updateBranding,
13
- uploadBrandingIcon,
14
- uploadBrandingLogo,
15
- uploadBrandingStylesheet,
16
- } from "@rapidmx/react-shared/branding/brandingApi.js";
17
- import Alert from "@rapidmx/react-shared/components/feedback/Alert.js";
18
- import Button from "@rapidmx/react-shared/components/buttons/Button.js";
19
- import CopyButton from "@rapidmx/react-shared/components/buttons/CopyButton.js";
20
-
21
- const INPUT_CLASS =
22
- "w-full text-sm py-2 px-3 border border-border rounded-sm bg-surface text-text focus:outline-none focus:border-primary";
23
-
24
- const MAX_UPLOAD_BYTES = 5 * 1024 * 1024;
25
-
26
- /** A header that uses both variables - the snippet the Branding page offers to copy. */
27
- export const HEADER_HTML_EXAMPLE = `<div style="display:flex; align-items:center; justify-content:space-between; padding:0.5rem 1rem">
28
- <span>{APP_TITLE}</span>
29
- <span>{USER_MENU}</span>
30
- </div>`;
31
-
32
- /** SVG logo/icon uploads are refused (the server refuses them too): an SVG served from this origin can carry script. */
33
- export function isSvgFile(file: File): boolean {
34
- return file.type === "image/svg+xml" || file.name.toLowerCase().endsWith(".svg");
35
- }
36
-
37
- const RASTER_IMAGE_ACCEPT = "image/png,image/jpeg,image/gif,image/webp,image/x-icon,image/vnd.microsoft.icon";
38
-
39
- export interface BrandingFormProps {
40
- branding: Branding;
41
- onChange: (b: Branding) => void;
42
- /** Set when shown in a page that already introduces branding (the setup wizard): the title and introduction are
43
- * left out, and the section headings sit one level lower. */
44
- embedded?: boolean;
45
- }
46
-
47
- /** The branding editor, shared by the Branding page and the setup wizard. */
48
- export default function BrandingForm({ branding, onChange, embedded = false }: BrandingFormProps) {
49
- const SectionHeading = embedded ? "h3" : "h2";
50
- const [companyName, setCompanyName] = useState(branding.companyName);
51
- const [title, setTitle] = useState(branding.title);
52
- const [headerHtml, setHeaderHtml] = useState(branding.headerHtml ?? "");
53
- const [footerHtml, setFooterHtml] = useState(branding.footerHtml ?? "");
54
- const [logoUrlInput, setLogoUrlInput] = useState(branding.logoUrl ?? "");
55
- const [iconUrlInput, setIconUrlInput] = useState(branding.iconUrl ?? "");
56
- const [stylesheetUrlInput, setStylesheetUrlInput] = useState(branding.stylesheetUrl ?? "");
57
-
58
- const [error, setError] = useState<string | null>(null);
59
- const [saving, setSaving] = useState(false);
60
- const [saved, setSaved] = useState(false);
61
- const [assetBusy, setAssetBusy] = useState<string | null>(null);
62
-
63
- const logoFileRef = useRef<HTMLInputElement>(null);
64
- const iconFileRef = useRef<HTMLInputElement>(null);
65
- const stylesheetFileRef = useRef<HTMLInputElement>(null);
66
-
67
- function runAsset(name: string, action: () => Promise<Branding>) {
68
- setError(null);
69
- setAssetBusy(name);
70
- return action()
71
- .then((updated) => {
72
- onChange(updated);
73
- setLogoUrlInput(updated.logoUrl ?? "");
74
- setIconUrlInput(updated.iconUrl ?? "");
75
- setStylesheetUrlInput(updated.stylesheetUrl ?? "");
76
- })
77
- .catch((err) => setError(err instanceof ApiRequestError ? err.message : "Could not update branding."))
78
- .finally(() => setAssetBusy(null));
79
- }
80
-
81
- function handleLogoFileChange(e: ChangeEvent<HTMLInputElement>) {
82
- const file = e.target.files?.[0];
83
- if (!file) return;
84
- if (isSvgFile(file)) {
85
- setError(`"${file.name}" is an SVG — upload a PNG, JPEG, GIF, or WebP logo instead.`);
86
- } else if (file.size > MAX_UPLOAD_BYTES) {
87
- setError(`"${file.name}" is too large — logos must be 5MB or smaller.`);
88
- } else {
89
- void runAsset("logo-upload", () => uploadBrandingLogo(file));
90
- }
91
- e.target.value = "";
92
- }
93
-
94
- function handleIconFileChange(e: ChangeEvent<HTMLInputElement>) {
95
- const file = e.target.files?.[0];
96
- if (!file) return;
97
- if (isSvgFile(file)) {
98
- setError(`"${file.name}" is an SVG — upload a PNG, JPEG, GIF, WebP, or ICO icon instead.`);
99
- } else if (file.size > MAX_UPLOAD_BYTES) {
100
- setError(`"${file.name}" is too large — icons must be 5MB or smaller.`);
101
- } else {
102
- void runAsset("icon-upload", () => uploadBrandingIcon(file));
103
- }
104
- e.target.value = "";
105
- }
106
-
107
- function handleStylesheetFileChange(e: ChangeEvent<HTMLInputElement>) {
108
- const file = e.target.files?.[0];
109
- if (!file) return;
110
- if (file.size > MAX_UPLOAD_BYTES) {
111
- setError(`"${file.name}" is too large — stylesheets must be 5MB or smaller.`);
112
- } else {
113
- void runAsset("stylesheet-upload", () => uploadBrandingStylesheet(file));
114
- }
115
- e.target.value = "";
116
- }
117
-
118
- async function handleSubmit(e: FormEvent) {
119
- e.preventDefault();
120
- setError(null);
121
- setSaved(false);
122
- setSaving(true);
123
- try {
124
- const updated = await updateBranding({ companyName, title, headerHtml, footerHtml });
125
- onChange(updated);
126
- setSaved(true);
127
- } catch (err) {
128
- setError(err instanceof ApiRequestError ? err.message : "Could not save branding.");
129
- } finally {
130
- setSaving(false);
131
- }
132
- }
133
-
134
- return (
135
- <div className="max-w-2xl">
136
- {!embedded && (
137
- <>
138
- <h1 className="text-xl font-bold uppercase tracking-wide mb-1">Branding</h1>
139
- <p className="text-sm text-text-muted mb-5">
140
- Customize the logo, nav-header icon, product name, and chrome shown to every visitor of the
141
- webmail and admin console — including anonymous booking-page visitors. The header appears on the
142
- webmail and public pages, not in the admin console; the footer appears in both.
143
- </p>
144
- </>
145
- )}
146
-
147
- {error && <Alert>{error}</Alert>}
148
- {saved && !error && <div className="mb-4 text-sm text-success font-medium">Saved.</div>}
149
-
150
- <div className="flex flex-col gap-6">
151
- <section className="flex flex-col gap-3">
152
- <SectionHeading className="text-sm font-bold uppercase tracking-wide text-text-muted">Logo</SectionHeading>
153
- <div className="flex items-center gap-4">
154
- <img
155
- src={branding.logoUrl || "/images/logo.svg"}
156
- alt="Current logo"
157
- width="64"
158
- height="64"
159
- className="border border-border rounded-sm bg-surface-alt p-1"
160
- />
161
- <div className="flex flex-col gap-2">
162
- <Button
163
- type="button"
164
- variant="secondary"
165
- className="!w-auto"
166
- loading={assetBusy === "logo-upload"}
167
- disabled={assetBusy !== null}
168
- onClick={() => logoFileRef.current?.click()}
169
- >
170
- Upload logo
171
- </Button>
172
- <input
173
- ref={logoFileRef}
174
- type="file"
175
- accept={RASTER_IMAGE_ACCEPT}
176
- aria-label="Upload logo"
177
- className="hidden"
178
- onChange={handleLogoFileChange}
179
- />
180
- {branding.logoUrl && (
181
- <Button
182
- type="button"
183
- variant="text"
184
- disabled={assetBusy !== null}
185
- loading={assetBusy === "logo-delete"}
186
- onClick={() => void runAsset("logo-delete", async () => {
187
- await deleteBrandingLogo();
188
- return { ...branding, logoUrl: undefined };
189
- })}
190
- >
191
- Remove logo
192
- </Button>
193
- )}
194
- </div>
195
- </div>
196
- <label className="flex flex-col gap-1.5 text-sm">
197
- <span className="font-semibold">Or use an external image URL</span>
198
- <div className="flex gap-2">
199
- <input
200
- aria-label="Logo URL"
201
- className={INPUT_CLASS}
202
- value={logoUrlInput}
203
- onChange={(e) => setLogoUrlInput(e.target.value)}
204
- />
205
- <Button
206
- type="button"
207
- variant="secondary"
208
- className="!w-auto"
209
- disabled={assetBusy !== null || logoUrlInput === (branding.logoUrl ?? "")}
210
- loading={assetBusy === "logo-url"}
211
- onClick={() => void runAsset("logo-url", () => updateBranding({ logoUrl: logoUrlInput }))}
212
- >
213
- Set
214
- </Button>
215
- </div>
216
- </label>
217
- </section>
218
-
219
- <section className="flex flex-col gap-3">
220
- <SectionHeading className="text-sm font-bold uppercase tracking-wide text-text-muted">Icon</SectionHeading>
221
- <p className="text-xs text-text-muted -mt-1">
222
- A compact mark for navigation headers, independent of the full logo above. Falls back to
223
- the logo, then a default asset, when not set.
224
- </p>
225
- <div className="flex items-center gap-4">
226
- <img
227
- src={branding.iconUrl || branding.logoUrl || "/images/logo.svg"}
228
- alt="Current icon"
229
- width="64"
230
- height="64"
231
- className="border border-border rounded-sm bg-surface-alt p-1"
232
- />
233
- <div className="flex flex-col gap-2">
234
- <Button
235
- type="button"
236
- variant="secondary"
237
- className="!w-auto"
238
- loading={assetBusy === "icon-upload"}
239
- disabled={assetBusy !== null}
240
- onClick={() => iconFileRef.current?.click()}
241
- >
242
- Upload icon
243
- </Button>
244
- <input
245
- ref={iconFileRef}
246
- type="file"
247
- accept={RASTER_IMAGE_ACCEPT}
248
- aria-label="Upload icon"
249
- className="hidden"
250
- onChange={handleIconFileChange}
251
- />
252
- {branding.iconUrl && (
253
- <Button
254
- type="button"
255
- variant="text"
256
- disabled={assetBusy !== null}
257
- loading={assetBusy === "icon-delete"}
258
- onClick={() => void runAsset("icon-delete", async () => {
259
- await deleteBrandingIcon();
260
- return { ...branding, iconUrl: undefined };
261
- })}
262
- >
263
- Remove icon
264
- </Button>
265
- )}
266
- </div>
267
- </div>
268
- <label className="flex flex-col gap-1.5 text-sm">
269
- <span className="font-semibold">Or use an external image URL</span>
270
- <div className="flex gap-2">
271
- <input
272
- aria-label="Icon URL"
273
- className={INPUT_CLASS}
274
- value={iconUrlInput}
275
- onChange={(e) => setIconUrlInput(e.target.value)}
276
- />
277
- <Button
278
- type="button"
279
- variant="secondary"
280
- className="!w-auto"
281
- disabled={assetBusy !== null || iconUrlInput === (branding.iconUrl ?? "")}
282
- loading={assetBusy === "icon-url"}
283
- onClick={() => void runAsset("icon-url", () => updateBranding({ iconUrl: iconUrlInput }))}
284
- >
285
- Set
286
- </Button>
287
- </div>
288
- </label>
289
- </section>
290
-
291
- <section className="flex flex-col gap-3">
292
- <SectionHeading className="text-sm font-bold uppercase tracking-wide text-text-muted">Custom stylesheet</SectionHeading>
293
- <div className="flex items-center gap-3">
294
- <span className="text-sm text-text-muted truncate">
295
- {branding.stylesheetUrl || "None configured"}
296
- </span>
297
- </div>
298
- <div className="flex gap-2">
299
- <Button
300
- type="button"
301
- variant="secondary"
302
- className="!w-auto"
303
- loading={assetBusy === "stylesheet-upload"}
304
- disabled={assetBusy !== null}
305
- onClick={() => stylesheetFileRef.current?.click()}
306
- >
307
- Upload CSS file
308
- </Button>
309
- <input
310
- ref={stylesheetFileRef}
311
- type="file"
312
- accept="text/css,.css"
313
- aria-label="Upload stylesheet"
314
- className="hidden"
315
- onChange={handleStylesheetFileChange}
316
- />
317
- {branding.stylesheetUrl && (
318
- <Button
319
- type="button"
320
- variant="text"
321
- disabled={assetBusy !== null}
322
- loading={assetBusy === "stylesheet-delete"}
323
- onClick={() => void runAsset("stylesheet-delete", async () => {
324
- await deleteBrandingStylesheet();
325
- return { ...branding, stylesheetUrl: undefined };
326
- })}
327
- >
328
- Remove stylesheet
329
- </Button>
330
- )}
331
- </div>
332
- <label className="flex flex-col gap-1.5 text-sm">
333
- <span className="font-semibold">Or use an external stylesheet URL</span>
334
- <div className="flex gap-2">
335
- <input
336
- aria-label="Stylesheet URL"
337
- className={INPUT_CLASS}
338
- value={stylesheetUrlInput}
339
- onChange={(e) => setStylesheetUrlInput(e.target.value)}
340
- />
341
- <Button
342
- type="button"
343
- variant="secondary"
344
- className="!w-auto"
345
- disabled={assetBusy !== null || stylesheetUrlInput === (branding.stylesheetUrl ?? "")}
346
- loading={assetBusy === "stylesheet-url"}
347
- onClick={() =>
348
- void runAsset("stylesheet-url", () => updateBranding({ stylesheetUrl: stylesheetUrlInput }))
349
- }
350
- >
351
- Set
352
- </Button>
353
- </div>
354
- </label>
355
- </section>
356
-
357
- <form onSubmit={handleSubmit} className="flex flex-col gap-4 pt-2 border-t border-border">
358
- <label className="flex flex-col gap-1.5 text-sm">
359
- <span className="font-semibold">Company name</span>
360
- <input
361
- aria-label="Company name"
362
- className={INPUT_CLASS}
363
- value={companyName}
364
- onChange={(e) => setCompanyName(e.target.value)}
365
- />
366
- </label>
367
- <label className="flex flex-col gap-1.5 text-sm">
368
- <span className="font-semibold">Product title</span>
369
- <input
370
- aria-label="Product title"
371
- className={INPUT_CLASS}
372
- value={title}
373
- onChange={(e) => setTitle(e.target.value)}
374
- />
375
- <span className="text-xs text-text-muted">Shown as the browser tab title.</span>
376
- </label>
377
- <label className="flex flex-col gap-1.5 text-sm">
378
- <span className="font-semibold">Header HTML (optional)</span>
379
- <textarea
380
- aria-label="Header HTML"
381
- className={`${INPUT_CLASS} font-mono`}
382
- rows={3}
383
- value={headerHtml}
384
- onChange={(e) => setHeaderHtml(e.target.value)}
385
- />
386
- <span className="text-xs text-text-muted">
387
- A header replaces the app's own title bar and the icon at the top of the icon rail, and stays at the top of the window. Write{" "}
388
- <code>{"{USER_MENU}"}</code> where the account menu (avatar, Settings, Sign Out) should go, and <code>{"{APP_TITLE}"}</code>{" "}
389
- where the name of the app on screen should show. Both work in the footer too. <code>{"{USER_MENU}"}</code> is replaced once
390
- (the header's, else the footer's); without it the menu sits in a small cell at the right end of the header, so it is never lost.
391
- Put it where your styles don't hide it on a phone.
392
- </span>
393
- </label>
394
- <div className="flex flex-col gap-1.5 text-sm" role="group" aria-label="Header example">
395
- <div className="flex items-center justify-between gap-2">
396
- <span className="font-semibold">Example header</span>
397
- <CopyButton value={HEADER_HTML_EXAMPLE} label="Copy the example header HTML" />
398
- </div>
399
- <pre className="overflow-x-auto rounded-sm border border-border bg-surface-alt p-3 font-mono text-xs text-text">{HEADER_HTML_EXAMPLE}</pre>
400
- </div>
401
- <label className="flex flex-col gap-1.5 text-sm">
402
- <span className="font-semibold">Footer HTML (optional)</span>
403
- <textarea
404
- aria-label="Footer HTML"
405
- className={`${INPUT_CLASS} font-mono`}
406
- rows={3}
407
- value={footerHtml}
408
- onChange={(e) => setFooterHtml(e.target.value)}
409
- />
410
- <span className="text-xs text-text-muted">
411
- <code>{"{APP_TITLE}"}</code> works here as well, and <code>{"{USER_MENU}"}</code> takes the account menu (opening upward) when the header has none.
412
- </span>
413
- </label>
414
- <div>
415
- <Button type="submit" loading={saving} disabled={saving} className="!w-auto">
416
- Save
417
- </Button>
418
- </div>
419
- </form>
420
- </div>
421
- </div>
422
- );
423
- }
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+ import React, { ChangeEvent, FormEvent, useRef, useState } from "react";
6
+ import { ApiRequestError } from "../../../../../lib/util/api.js";
7
+ import {
8
+ Branding,
9
+ deleteBrandingIcon,
10
+ deleteBrandingLogo,
11
+ deleteBrandingStylesheet,
12
+ updateBranding,
13
+ uploadBrandingIcon,
14
+ uploadBrandingLogo,
15
+ uploadBrandingStylesheet,
16
+ } from "../../../../../lib/branding/brandingApi.js";
17
+ import Alert from "../../../../../lib/components/feedback/Alert.js";
18
+ import Button from "../../../../../lib/components/buttons/Button.js";
19
+ import CopyButton from "../../../../../lib/components/buttons/CopyButton.js";
20
+
21
+ const INPUT_CLASS =
22
+ "w-full text-sm py-2 px-3 border border-border rounded-sm bg-surface text-text focus:outline-none focus:border-primary";
23
+
24
+ const MAX_UPLOAD_BYTES = 5 * 1024 * 1024;
25
+
26
+ /** A header that uses both variables - the snippet the Branding page offers to copy. */
27
+ export const HEADER_HTML_EXAMPLE = `<div style="display:flex; align-items:center; justify-content:space-between; padding:0.5rem 1rem">
28
+ <span>{APP_TITLE}</span>
29
+ <span>{USER_MENU}</span>
30
+ </div>`;
31
+
32
+ /** SVG logo/icon uploads are refused (the server refuses them too): an SVG served from this origin can carry script. */
33
+ export function isSvgFile(file: File): boolean {
34
+ return file.type === "image/svg+xml" || file.name.toLowerCase().endsWith(".svg");
35
+ }
36
+
37
+ const RASTER_IMAGE_ACCEPT = "image/png,image/jpeg,image/gif,image/webp,image/x-icon,image/vnd.microsoft.icon";
38
+
39
+ export interface BrandingFormProps {
40
+ branding: Branding;
41
+ onChange: (b: Branding) => void;
42
+ /** Set when shown in a page that already introduces branding (the setup wizard): the title and introduction are
43
+ * left out, and the section headings sit one level lower. */
44
+ embedded?: boolean;
45
+ }
46
+
47
+ /** The branding editor, shared by the Branding page and the setup wizard. */
48
+ export default function BrandingForm({ branding, onChange, embedded = false }: BrandingFormProps) {
49
+ const SectionHeading = embedded ? "h3" : "h2";
50
+ const [companyName, setCompanyName] = useState(branding.companyName);
51
+ const [title, setTitle] = useState(branding.title);
52
+ const [headerHtml, setHeaderHtml] = useState(branding.headerHtml ?? "");
53
+ const [footerHtml, setFooterHtml] = useState(branding.footerHtml ?? "");
54
+ const [logoUrlInput, setLogoUrlInput] = useState(branding.logoUrl ?? "");
55
+ const [iconUrlInput, setIconUrlInput] = useState(branding.iconUrl ?? "");
56
+ const [stylesheetUrlInput, setStylesheetUrlInput] = useState(branding.stylesheetUrl ?? "");
57
+
58
+ const [error, setError] = useState<string | null>(null);
59
+ const [saving, setSaving] = useState(false);
60
+ const [saved, setSaved] = useState(false);
61
+ const [assetBusy, setAssetBusy] = useState<string | null>(null);
62
+
63
+ const logoFileRef = useRef<HTMLInputElement>(null);
64
+ const iconFileRef = useRef<HTMLInputElement>(null);
65
+ const stylesheetFileRef = useRef<HTMLInputElement>(null);
66
+
67
+ function runAsset(name: string, action: () => Promise<Branding>) {
68
+ setError(null);
69
+ setAssetBusy(name);
70
+ return action()
71
+ .then((updated) => {
72
+ onChange(updated);
73
+ setLogoUrlInput(updated.logoUrl ?? "");
74
+ setIconUrlInput(updated.iconUrl ?? "");
75
+ setStylesheetUrlInput(updated.stylesheetUrl ?? "");
76
+ })
77
+ .catch((err) => setError(err instanceof ApiRequestError ? err.message : "Could not update branding."))
78
+ .finally(() => setAssetBusy(null));
79
+ }
80
+
81
+ function handleLogoFileChange(e: ChangeEvent<HTMLInputElement>) {
82
+ const file = e.target.files?.[0];
83
+ if (!file) return;
84
+ if (isSvgFile(file)) {
85
+ setError(`"${file.name}" is an SVG — upload a PNG, JPEG, GIF, or WebP logo instead.`);
86
+ } else if (file.size > MAX_UPLOAD_BYTES) {
87
+ setError(`"${file.name}" is too large — logos must be 5MB or smaller.`);
88
+ } else {
89
+ void runAsset("logo-upload", () => uploadBrandingLogo(file));
90
+ }
91
+ e.target.value = "";
92
+ }
93
+
94
+ function handleIconFileChange(e: ChangeEvent<HTMLInputElement>) {
95
+ const file = e.target.files?.[0];
96
+ if (!file) return;
97
+ if (isSvgFile(file)) {
98
+ setError(`"${file.name}" is an SVG — upload a PNG, JPEG, GIF, WebP, or ICO icon instead.`);
99
+ } else if (file.size > MAX_UPLOAD_BYTES) {
100
+ setError(`"${file.name}" is too large — icons must be 5MB or smaller.`);
101
+ } else {
102
+ void runAsset("icon-upload", () => uploadBrandingIcon(file));
103
+ }
104
+ e.target.value = "";
105
+ }
106
+
107
+ function handleStylesheetFileChange(e: ChangeEvent<HTMLInputElement>) {
108
+ const file = e.target.files?.[0];
109
+ if (!file) return;
110
+ if (file.size > MAX_UPLOAD_BYTES) {
111
+ setError(`"${file.name}" is too large — stylesheets must be 5MB or smaller.`);
112
+ } else {
113
+ void runAsset("stylesheet-upload", () => uploadBrandingStylesheet(file));
114
+ }
115
+ e.target.value = "";
116
+ }
117
+
118
+ async function handleSubmit(e: FormEvent) {
119
+ e.preventDefault();
120
+ setError(null);
121
+ setSaved(false);
122
+ setSaving(true);
123
+ try {
124
+ const updated = await updateBranding({ companyName, title, headerHtml, footerHtml });
125
+ onChange(updated);
126
+ setSaved(true);
127
+ } catch (err) {
128
+ setError(err instanceof ApiRequestError ? err.message : "Could not save branding.");
129
+ } finally {
130
+ setSaving(false);
131
+ }
132
+ }
133
+
134
+ return (
135
+ <div className="max-w-2xl">
136
+ {!embedded && (
137
+ <>
138
+ <h1 className="text-xl font-bold uppercase tracking-wide mb-1">Branding</h1>
139
+ <p className="text-sm text-text-muted mb-5">
140
+ Customize the logo, nav-header icon, product name, and chrome shown to every visitor of the
141
+ webmail and admin console — including anonymous booking-page visitors. The header appears on the
142
+ webmail and public pages, not in the admin console; the footer appears in both.
143
+ </p>
144
+ </>
145
+ )}
146
+
147
+ {error && <Alert>{error}</Alert>}
148
+ {saved && !error && <div className="mb-4 text-sm text-success font-medium">Saved.</div>}
149
+
150
+ <div className="flex flex-col gap-6">
151
+ <section className="flex flex-col gap-3">
152
+ <SectionHeading className="text-sm font-bold uppercase tracking-wide text-text-muted">Logo</SectionHeading>
153
+ <div className="flex items-center gap-4">
154
+ <img
155
+ src={branding.logoUrl || "/images/logo.svg"}
156
+ alt="Current logo"
157
+ width="64"
158
+ height="64"
159
+ className="border border-border rounded-sm bg-surface-alt p-1"
160
+ />
161
+ <div className="flex flex-col gap-2">
162
+ <Button
163
+ type="button"
164
+ variant="secondary"
165
+ className="!w-auto"
166
+ loading={assetBusy === "logo-upload"}
167
+ disabled={assetBusy !== null}
168
+ onClick={() => logoFileRef.current?.click()}
169
+ >
170
+ Upload logo
171
+ </Button>
172
+ <input
173
+ ref={logoFileRef}
174
+ type="file"
175
+ accept={RASTER_IMAGE_ACCEPT}
176
+ aria-label="Upload logo"
177
+ className="hidden"
178
+ onChange={handleLogoFileChange}
179
+ />
180
+ {branding.logoUrl && (
181
+ <Button
182
+ type="button"
183
+ variant="text"
184
+ disabled={assetBusy !== null}
185
+ loading={assetBusy === "logo-delete"}
186
+ onClick={() => void runAsset("logo-delete", async () => {
187
+ await deleteBrandingLogo();
188
+ return { ...branding, logoUrl: undefined };
189
+ })}
190
+ >
191
+ Remove logo
192
+ </Button>
193
+ )}
194
+ </div>
195
+ </div>
196
+ <label className="flex flex-col gap-1.5 text-sm">
197
+ <span className="font-semibold">Or use an external image URL</span>
198
+ <div className="flex gap-2">
199
+ <input
200
+ aria-label="Logo URL"
201
+ className={INPUT_CLASS}
202
+ value={logoUrlInput}
203
+ onChange={(e) => setLogoUrlInput(e.target.value)}
204
+ />
205
+ <Button
206
+ type="button"
207
+ variant="secondary"
208
+ className="!w-auto"
209
+ disabled={assetBusy !== null || logoUrlInput === (branding.logoUrl ?? "")}
210
+ loading={assetBusy === "logo-url"}
211
+ onClick={() => void runAsset("logo-url", () => updateBranding({ logoUrl: logoUrlInput }))}
212
+ >
213
+ Set
214
+ </Button>
215
+ </div>
216
+ </label>
217
+ </section>
218
+
219
+ <section className="flex flex-col gap-3">
220
+ <SectionHeading className="text-sm font-bold uppercase tracking-wide text-text-muted">Icon</SectionHeading>
221
+ <p className="text-xs text-text-muted -mt-1">
222
+ A compact mark for navigation headers, independent of the full logo above. Falls back to
223
+ the logo, then a default asset, when not set.
224
+ </p>
225
+ <div className="flex items-center gap-4">
226
+ <img
227
+ src={branding.iconUrl || branding.logoUrl || "/images/logo.svg"}
228
+ alt="Current icon"
229
+ width="64"
230
+ height="64"
231
+ className="border border-border rounded-sm bg-surface-alt p-1"
232
+ />
233
+ <div className="flex flex-col gap-2">
234
+ <Button
235
+ type="button"
236
+ variant="secondary"
237
+ className="!w-auto"
238
+ loading={assetBusy === "icon-upload"}
239
+ disabled={assetBusy !== null}
240
+ onClick={() => iconFileRef.current?.click()}
241
+ >
242
+ Upload icon
243
+ </Button>
244
+ <input
245
+ ref={iconFileRef}
246
+ type="file"
247
+ accept={RASTER_IMAGE_ACCEPT}
248
+ aria-label="Upload icon"
249
+ className="hidden"
250
+ onChange={handleIconFileChange}
251
+ />
252
+ {branding.iconUrl && (
253
+ <Button
254
+ type="button"
255
+ variant="text"
256
+ disabled={assetBusy !== null}
257
+ loading={assetBusy === "icon-delete"}
258
+ onClick={() => void runAsset("icon-delete", async () => {
259
+ await deleteBrandingIcon();
260
+ return { ...branding, iconUrl: undefined };
261
+ })}
262
+ >
263
+ Remove icon
264
+ </Button>
265
+ )}
266
+ </div>
267
+ </div>
268
+ <label className="flex flex-col gap-1.5 text-sm">
269
+ <span className="font-semibold">Or use an external image URL</span>
270
+ <div className="flex gap-2">
271
+ <input
272
+ aria-label="Icon URL"
273
+ className={INPUT_CLASS}
274
+ value={iconUrlInput}
275
+ onChange={(e) => setIconUrlInput(e.target.value)}
276
+ />
277
+ <Button
278
+ type="button"
279
+ variant="secondary"
280
+ className="!w-auto"
281
+ disabled={assetBusy !== null || iconUrlInput === (branding.iconUrl ?? "")}
282
+ loading={assetBusy === "icon-url"}
283
+ onClick={() => void runAsset("icon-url", () => updateBranding({ iconUrl: iconUrlInput }))}
284
+ >
285
+ Set
286
+ </Button>
287
+ </div>
288
+ </label>
289
+ </section>
290
+
291
+ <section className="flex flex-col gap-3">
292
+ <SectionHeading className="text-sm font-bold uppercase tracking-wide text-text-muted">Custom stylesheet</SectionHeading>
293
+ <div className="flex items-center gap-3">
294
+ <span className="text-sm text-text-muted truncate">
295
+ {branding.stylesheetUrl || "None configured"}
296
+ </span>
297
+ </div>
298
+ <div className="flex gap-2">
299
+ <Button
300
+ type="button"
301
+ variant="secondary"
302
+ className="!w-auto"
303
+ loading={assetBusy === "stylesheet-upload"}
304
+ disabled={assetBusy !== null}
305
+ onClick={() => stylesheetFileRef.current?.click()}
306
+ >
307
+ Upload CSS file
308
+ </Button>
309
+ <input
310
+ ref={stylesheetFileRef}
311
+ type="file"
312
+ accept="text/css,.css"
313
+ aria-label="Upload stylesheet"
314
+ className="hidden"
315
+ onChange={handleStylesheetFileChange}
316
+ />
317
+ {branding.stylesheetUrl && (
318
+ <Button
319
+ type="button"
320
+ variant="text"
321
+ disabled={assetBusy !== null}
322
+ loading={assetBusy === "stylesheet-delete"}
323
+ onClick={() => void runAsset("stylesheet-delete", async () => {
324
+ await deleteBrandingStylesheet();
325
+ return { ...branding, stylesheetUrl: undefined };
326
+ })}
327
+ >
328
+ Remove stylesheet
329
+ </Button>
330
+ )}
331
+ </div>
332
+ <label className="flex flex-col gap-1.5 text-sm">
333
+ <span className="font-semibold">Or use an external stylesheet URL</span>
334
+ <div className="flex gap-2">
335
+ <input
336
+ aria-label="Stylesheet URL"
337
+ className={INPUT_CLASS}
338
+ value={stylesheetUrlInput}
339
+ onChange={(e) => setStylesheetUrlInput(e.target.value)}
340
+ />
341
+ <Button
342
+ type="button"
343
+ variant="secondary"
344
+ className="!w-auto"
345
+ disabled={assetBusy !== null || stylesheetUrlInput === (branding.stylesheetUrl ?? "")}
346
+ loading={assetBusy === "stylesheet-url"}
347
+ onClick={() =>
348
+ void runAsset("stylesheet-url", () => updateBranding({ stylesheetUrl: stylesheetUrlInput }))
349
+ }
350
+ >
351
+ Set
352
+ </Button>
353
+ </div>
354
+ </label>
355
+ </section>
356
+
357
+ <form onSubmit={handleSubmit} className="flex flex-col gap-4 pt-2 border-t border-border">
358
+ <label className="flex flex-col gap-1.5 text-sm">
359
+ <span className="font-semibold">Company name</span>
360
+ <input
361
+ aria-label="Company name"
362
+ className={INPUT_CLASS}
363
+ value={companyName}
364
+ onChange={(e) => setCompanyName(e.target.value)}
365
+ />
366
+ </label>
367
+ <label className="flex flex-col gap-1.5 text-sm">
368
+ <span className="font-semibold">Product title</span>
369
+ <input
370
+ aria-label="Product title"
371
+ className={INPUT_CLASS}
372
+ value={title}
373
+ onChange={(e) => setTitle(e.target.value)}
374
+ />
375
+ <span className="text-xs text-text-muted">Shown as the browser tab title.</span>
376
+ </label>
377
+ <label className="flex flex-col gap-1.5 text-sm">
378
+ <span className="font-semibold">Header HTML (optional)</span>
379
+ <textarea
380
+ aria-label="Header HTML"
381
+ className={`${INPUT_CLASS} font-mono`}
382
+ rows={3}
383
+ value={headerHtml}
384
+ onChange={(e) => setHeaderHtml(e.target.value)}
385
+ />
386
+ <span className="text-xs text-text-muted">
387
+ A header replaces the app's own title bar and the icon at the top of the icon rail, and stays at the top of the window. Write{" "}
388
+ <code>{"{USER_MENU}"}</code> where the account menu (avatar, Settings, Sign Out) should go, and <code>{"{APP_TITLE}"}</code>{" "}
389
+ where the name of the app on screen should show. Both work in the footer too. <code>{"{USER_MENU}"}</code> is replaced once
390
+ (the header's, else the footer's); without it the menu sits in a small cell at the right end of the header, so it is never lost.
391
+ Put it where your styles don't hide it on a phone.
392
+ </span>
393
+ </label>
394
+ <div className="flex flex-col gap-1.5 text-sm" role="group" aria-label="Header example">
395
+ <div className="flex items-center justify-between gap-2">
396
+ <span className="font-semibold">Example header</span>
397
+ <CopyButton value={HEADER_HTML_EXAMPLE} label="Copy the example header HTML" />
398
+ </div>
399
+ <pre className="overflow-x-auto rounded-sm border border-border bg-surface-alt p-3 font-mono text-xs text-text">{HEADER_HTML_EXAMPLE}</pre>
400
+ </div>
401
+ <label className="flex flex-col gap-1.5 text-sm">
402
+ <span className="font-semibold">Footer HTML (optional)</span>
403
+ <textarea
404
+ aria-label="Footer HTML"
405
+ className={`${INPUT_CLASS} font-mono`}
406
+ rows={3}
407
+ value={footerHtml}
408
+ onChange={(e) => setFooterHtml(e.target.value)}
409
+ />
410
+ <span className="text-xs text-text-muted">
411
+ <code>{"{APP_TITLE}"}</code> works here as well, and <code>{"{USER_MENU}"}</code> takes the account menu (opening upward) when the header has none.
412
+ </span>
413
+ </label>
414
+ <div>
415
+ <Button type="submit" loading={saving} disabled={saving} className="!w-auto">
416
+ Save
417
+ </Button>
418
+ </div>
419
+ </form>
420
+ </div>
421
+ </div>
422
+ );
423
+ }