@rapidmx/web-client 0.14.0 → 0.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/apps/admin/domains/[uid].tsx +3 -2
  2. package/apps/shared/appearance/AppearanceForm.tsx +9 -1
  3. package/apps/shared/calendar/bookingPlugin.ts +100 -0
  4. package/apps/shared/calendar/calendarLiveUpdates.ts +27 -0
  5. package/apps/shared/components/admin/layout/AdminShell.tsx +37 -5
  6. package/apps/shared/components/admin/settings/MailboxCreateForm.tsx +3 -1
  7. package/apps/shared/components/admin/settings/PluginsManager.tsx +1545 -1491
  8. package/apps/shared/components/calendar/AppointmentQuickForm.tsx +327 -0
  9. package/apps/shared/components/calendar/DescriptionEditor.tsx +274 -0
  10. package/apps/shared/components/calendar/EventDescriptionView.tsx +70 -0
  11. package/apps/shared/components/calendar/EventDetails.tsx +401 -0
  12. package/apps/shared/components/calendar/EventEditor.tsx +640 -0
  13. package/apps/shared/components/calendar/EventExpandedForm.tsx +210 -0
  14. package/apps/shared/components/calendar/EventFormParts.tsx +622 -0
  15. package/apps/shared/components/calendar/EventModal.tsx +126 -862
  16. package/apps/shared/components/calendar/EventQuickForm.tsx +116 -0
  17. package/apps/shared/components/calendar/EventShell.tsx +202 -0
  18. package/apps/shared/components/calendar/FindATime.tsx +379 -0
  19. package/apps/shared/components/calendar/LazyDescriptionEditor.tsx +70 -0
  20. package/apps/shared/components/calendar/MonthView.tsx +15 -3
  21. package/apps/shared/components/calendar/QuickCreateFaces.tsx +87 -0
  22. package/apps/shared/components/calendar/QuickCreateTabs.tsx +81 -0
  23. package/apps/shared/components/calendar/QuickFaceFrame.tsx +81 -0
  24. package/apps/shared/components/calendar/RecurrenceEditor.tsx +10 -5
  25. package/apps/shared/components/calendar/RequestChangeForm.tsx +271 -0
  26. package/apps/shared/components/calendar/SplitDayView.tsx +6 -5
  27. package/apps/shared/components/calendar/TaskQuickForm.tsx +289 -0
  28. package/apps/shared/components/calendar/TimeGridView.tsx +8 -6
  29. package/apps/shared/components/calendar/eventDialogFields.ts +86 -0
  30. package/apps/shared/components/calendar/eventForm.ts +108 -0
  31. package/apps/shared/components/calendar/eventFormat.ts +183 -0
  32. package/apps/shared/components/calendar/findTimeGrid.ts +90 -0
  33. package/apps/shared/components/calendar/swipeNavigation.ts +14 -0
  34. package/apps/shared/components/layout/UserMenu.tsx +80 -28
  35. package/apps/shared/components/mail/ConversationList.tsx +100 -48
  36. package/apps/shared/components/mail/ConversationThreadPane.tsx +490 -486
  37. package/apps/shared/components/mail/InviteCard.tsx +387 -0
  38. package/apps/shared/components/mail/MessageDetailPane.tsx +24 -2
  39. package/apps/shared/components/mail/SwipeRow.tsx +120 -0
  40. package/apps/shared/components/mail/compose/ComposeWindow.tsx +7 -3
  41. package/apps/shared/components/mail/invite/InviteRowChip.tsx +104 -0
  42. package/apps/shared/components/mail/invite/InviteRsvpPopover.tsx +271 -0
  43. package/apps/shared/components/mail/invite/InviteTimeline.tsx +200 -0
  44. package/apps/shared/components/mail/invite/ProposeTimeForm.tsx +109 -0
  45. package/apps/shared/components/mail/invite/inviteFormat.ts +110 -0
  46. package/apps/shared/components/mail/invite/inviteStore.ts +114 -0
  47. package/apps/shared/components/mail/layout/MailShell.tsx +522 -490
  48. package/apps/shared/components/settings/layout/SettingsShell.tsx +1 -0
  49. package/apps/shared/gestures/useEnterSlide.ts +54 -0
  50. package/apps/shared/gestures/useSwipe.ts +114 -0
  51. package/apps/shared/gestures/useSwipeSlide.ts +113 -0
  52. package/apps/shared/gestures/useWheelPaging.ts +107 -0
  53. package/apps/shared/mail/newMailNotifications.ts +171 -183
  54. package/apps/shared/mail/useNewMailNotifications.ts +178 -178
  55. package/apps/shared/notifications/preferences.ts +36 -0
  56. package/apps/shared/notifications/store.ts +560 -551
  57. package/apps/www/_routes.ts +1 -0
  58. package/apps/www/calendar/index.tsx +139 -37
  59. package/apps/www/index.tsx +273 -126
  60. package/apps/www/messages/[uid].tsx +31 -4
  61. package/apps/www/settings/profile/index.tsx +248 -0
  62. package/dist/apps/admin/domains/[uid].js +4 -2
  63. package/dist/apps/shared/appearance/AppearanceForm.js +9 -1
  64. package/dist/apps/shared/calendar/bookingPlugin.d.ts +50 -0
  65. package/dist/apps/shared/calendar/bookingPlugin.js +57 -0
  66. package/dist/apps/shared/calendar/calendarLiveUpdates.d.ts +11 -0
  67. package/dist/apps/shared/calendar/calendarLiveUpdates.js +23 -0
  68. package/dist/apps/shared/components/admin/layout/AdminShell.d.ts +1 -1
  69. package/dist/apps/shared/components/admin/layout/AdminShell.js +7 -3
  70. package/dist/apps/shared/components/admin/settings/MailboxCreateForm.js +3 -1
  71. package/dist/apps/shared/components/admin/settings/PluginsManager.js +40 -6
  72. package/dist/apps/shared/components/calendar/AppointmentQuickForm.d.ts +47 -0
  73. package/dist/apps/shared/components/calendar/AppointmentQuickForm.js +135 -0
  74. package/dist/apps/shared/components/calendar/DescriptionEditor.d.ts +26 -0
  75. package/dist/apps/shared/components/calendar/DescriptionEditor.js +192 -0
  76. package/dist/apps/shared/components/calendar/EventDescriptionView.d.ts +14 -0
  77. package/dist/apps/shared/components/calendar/EventDescriptionView.js +39 -0
  78. package/dist/apps/shared/components/calendar/EventDetails.d.ts +33 -0
  79. package/dist/apps/shared/components/calendar/EventDetails.js +137 -0
  80. package/dist/apps/shared/components/calendar/EventEditor.d.ts +59 -0
  81. package/dist/apps/shared/components/calendar/EventEditor.js +549 -0
  82. package/dist/apps/shared/components/calendar/EventExpandedForm.d.ts +14 -0
  83. package/dist/apps/shared/components/calendar/EventExpandedForm.js +44 -0
  84. package/dist/apps/shared/components/calendar/EventFormParts.d.ts +69 -0
  85. package/dist/apps/shared/components/calendar/EventFormParts.js +202 -0
  86. package/dist/apps/shared/components/calendar/EventModal.d.ts +26 -13
  87. package/dist/apps/shared/components/calendar/EventModal.js +57 -455
  88. package/dist/apps/shared/components/calendar/EventQuickForm.d.ts +18 -0
  89. package/dist/apps/shared/components/calendar/EventQuickForm.js +25 -0
  90. package/dist/apps/shared/components/calendar/EventShell.d.ts +64 -0
  91. package/dist/apps/shared/components/calendar/EventShell.js +134 -0
  92. package/dist/apps/shared/components/calendar/FindATime.d.ts +18 -0
  93. package/dist/apps/shared/components/calendar/FindATime.js +190 -0
  94. package/dist/apps/shared/components/calendar/LazyDescriptionEditor.d.ts +8 -0
  95. package/dist/apps/shared/components/calendar/LazyDescriptionEditor.js +44 -0
  96. package/dist/apps/shared/components/calendar/MonthView.d.ts +5 -1
  97. package/dist/apps/shared/components/calendar/MonthView.js +11 -5
  98. package/dist/apps/shared/components/calendar/QuickCreateFaces.d.ts +30 -0
  99. package/dist/apps/shared/components/calendar/QuickCreateFaces.js +44 -0
  100. package/dist/apps/shared/components/calendar/QuickCreateTabs.d.ts +24 -0
  101. package/dist/apps/shared/components/calendar/QuickCreateTabs.js +46 -0
  102. package/dist/apps/shared/components/calendar/QuickFaceFrame.d.ts +25 -0
  103. package/dist/apps/shared/components/calendar/QuickFaceFrame.js +19 -0
  104. package/dist/apps/shared/components/calendar/RecurrenceEditor.d.ts +4 -1
  105. package/dist/apps/shared/components/calendar/RecurrenceEditor.js +2 -2
  106. package/dist/apps/shared/components/calendar/RequestChangeForm.d.ts +36 -0
  107. package/dist/apps/shared/components/calendar/RequestChangeForm.js +138 -0
  108. package/dist/apps/shared/components/calendar/SplitDayView.d.ts +3 -2
  109. package/dist/apps/shared/components/calendar/SplitDayView.js +3 -2
  110. package/dist/apps/shared/components/calendar/TaskQuickForm.d.ts +40 -0
  111. package/dist/apps/shared/components/calendar/TaskQuickForm.js +101 -0
  112. package/dist/apps/shared/components/calendar/TimeGridView.d.ts +4 -2
  113. package/dist/apps/shared/components/calendar/TimeGridView.js +3 -2
  114. package/dist/apps/shared/components/calendar/eventDialogFields.d.ts +28 -0
  115. package/dist/apps/shared/components/calendar/eventDialogFields.js +59 -0
  116. package/dist/apps/shared/components/calendar/eventForm.d.ts +98 -0
  117. package/dist/apps/shared/components/calendar/eventForm.js +1 -0
  118. package/dist/apps/shared/components/calendar/eventFormat.d.ts +67 -0
  119. package/dist/apps/shared/components/calendar/eventFormat.js +163 -0
  120. package/dist/apps/shared/components/calendar/findTimeGrid.d.ts +30 -0
  121. package/dist/apps/shared/components/calendar/findTimeGrid.js +83 -0
  122. package/dist/apps/shared/components/calendar/swipeNavigation.d.ts +9 -0
  123. package/dist/apps/shared/components/calendar/swipeNavigation.js +8 -0
  124. package/dist/apps/shared/components/layout/UserMenu.d.ts +10 -8
  125. package/dist/apps/shared/components/layout/UserMenu.js +70 -23
  126. package/dist/apps/shared/components/mail/ConversationList.d.ts +12 -1
  127. package/dist/apps/shared/components/mail/ConversationList.js +21 -4
  128. package/dist/apps/shared/components/mail/ConversationThreadPane.d.ts +4 -1
  129. package/dist/apps/shared/components/mail/InviteCard.d.ts +20 -0
  130. package/dist/apps/shared/components/mail/InviteCard.js +150 -0
  131. package/dist/apps/shared/components/mail/MessageDetailPane.js +13 -2
  132. package/dist/apps/shared/components/mail/SwipeRow.d.ts +22 -0
  133. package/dist/apps/shared/components/mail/SwipeRow.js +71 -0
  134. package/dist/apps/shared/components/mail/compose/ComposeWindow.js +8 -3
  135. package/dist/apps/shared/components/mail/invite/InviteRowChip.d.ts +23 -0
  136. package/dist/apps/shared/components/mail/invite/InviteRowChip.js +46 -0
  137. package/dist/apps/shared/components/mail/invite/InviteRsvpPopover.d.ts +20 -0
  138. package/dist/apps/shared/components/mail/invite/InviteRsvpPopover.js +141 -0
  139. package/dist/apps/shared/components/mail/invite/InviteTimeline.d.ts +27 -0
  140. package/dist/apps/shared/components/mail/invite/InviteTimeline.js +120 -0
  141. package/dist/apps/shared/components/mail/invite/ProposeTimeForm.d.ts +17 -0
  142. package/dist/apps/shared/components/mail/invite/ProposeTimeForm.js +45 -0
  143. package/dist/apps/shared/components/mail/invite/inviteFormat.d.ts +28 -0
  144. package/dist/apps/shared/components/mail/invite/inviteFormat.js +94 -0
  145. package/dist/apps/shared/components/mail/invite/inviteStore.d.ts +28 -0
  146. package/dist/apps/shared/components/mail/invite/inviteStore.js +95 -0
  147. package/dist/apps/shared/components/mail/layout/MailShell.d.ts +5 -0
  148. package/dist/apps/shared/components/mail/layout/MailShell.js +14 -3
  149. package/dist/apps/shared/components/settings/layout/SettingsShell.js +1 -0
  150. package/dist/apps/shared/gestures/useEnterSlide.d.ts +14 -0
  151. package/dist/apps/shared/gestures/useEnterSlide.js +47 -0
  152. package/dist/apps/shared/gestures/useSwipe.d.ts +45 -0
  153. package/dist/apps/shared/gestures/useSwipe.js +90 -0
  154. package/dist/apps/shared/gestures/useSwipeSlide.d.ts +40 -0
  155. package/dist/apps/shared/gestures/useSwipeSlide.js +95 -0
  156. package/dist/apps/shared/gestures/useWheelPaging.d.ts +32 -0
  157. package/dist/apps/shared/gestures/useWheelPaging.js +85 -0
  158. package/dist/apps/shared/mail/newMailNotifications.d.ts +3 -8
  159. package/dist/apps/shared/mail/newMailNotifications.js +3 -12
  160. package/dist/apps/shared/mail/useNewMailNotifications.js +3 -2
  161. package/dist/apps/shared/notifications/preferences.d.ts +13 -0
  162. package/dist/apps/shared/notifications/preferences.js +36 -0
  163. package/dist/apps/shared/notifications/store.d.ts +1 -0
  164. package/dist/apps/shared/notifications/store.js +7 -23
  165. package/dist/apps/www/_routes.js +1 -0
  166. package/dist/apps/www/calendar/index.js +76 -6
  167. package/dist/apps/www/index.js +140 -39
  168. package/dist/apps/www/messages/[uid].js +13 -5
  169. package/dist/apps/www/settings/profile/index.d.ts +4 -0
  170. package/dist/apps/www/settings/profile/index.js +124 -0
  171. package/package.json +3 -3
@@ -0,0 +1,210 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+ import React, { KeyboardEvent, useRef, useState } from "react";
6
+ import { HiOutlineBriefcase, HiOutlineCalendarDays, HiOutlineXMark } from "react-icons/hi2";
7
+ import { BusyStatus } from "@rapidmx/react-shared/calendar/calendarApi.js";
8
+ import Alert from "@rapidmx/react-shared/components/feedback/Alert.js";
9
+ import Button from "@rapidmx/react-shared/components/buttons/Button.js";
10
+ import FindATime from "./FindATime.js";
11
+ import {
12
+ CalendarField,
13
+ DateTimeControls,
14
+ DescriptionRow,
15
+ GuestPermissions,
16
+ GuestsField,
17
+ INPUT_CLASS,
18
+ IconRow,
19
+ LocationRow,
20
+ ReminderRow,
21
+ VideoConferencingRow,
22
+ VisibilitySelect,
23
+ } from "./EventFormParts.js";
24
+ import { EventFormController } from "./eventForm.js";
25
+ import { BUSY_STATUSES, BUSY_STATUS_LABEL } from "./eventFormat.js";
26
+
27
+ type Tab = "details" | "find";
28
+ const TABS: { tab: Tab; label: string }[] = [
29
+ { tab: "details", label: "Event details" },
30
+ { tab: "find", label: "Find a time" },
31
+ ];
32
+
33
+ /**
34
+ * The full event form, as a card: a close button and Save across the top, the title, when (dates, times, All day, Time zone, how it
35
+ * repeats), and two columns - the event's details or Find a time on the left, the guests on the right. What "More options" opens for a new event and what Modify opens for an existing one.
36
+ *
37
+ * The left column has two tabs, as Google Calendar's card does: "Event details" - video conferencing, location, the description (a rich-text box),
38
+ * the reminder, calendar, busy status and visibility, and the automatic reply - and "Find a time" (`FindATime`), a day of the guests' calendars side by side.
39
+ * The guests stay on the right whichever tab is showing, with the permissions guests have over the event underneath. The details are hidden, not removed,
40
+ * while Find a time shows, so nothing typed in them is lost.
41
+ */
42
+ export default function EventExpandedForm({ c }: { c: EventFormController }) {
43
+ const { values } = c;
44
+ const [tab, setTab] = useState<Tab>("details");
45
+ const tabButtons = useRef<Record<Tab, HTMLButtonElement | null>>({ details: null, find: null });
46
+
47
+ function handleTabKeyDown(event: KeyboardEvent<HTMLButtonElement>) {
48
+ if (event.key === "ArrowRight" || event.key === "ArrowLeft" || event.key === "Home" || event.key === "End") {
49
+ event.preventDefault();
50
+ const next: Tab = event.key === "ArrowRight" || event.key === "End" ? "find" : "details";
51
+ setTab(next);
52
+ tabButtons.current[next]!.focus();
53
+ }
54
+ }
55
+
56
+ return (
57
+ <form onSubmit={c.onSubmit} className="flex flex-col">
58
+ <div className="flex items-center justify-between px-3 pt-3">
59
+ <button
60
+ type="button"
61
+ aria-label="Close"
62
+ onClick={c.onCancel}
63
+ className="w-8 h-8 flex items-center justify-center rounded-full text-text-muted hover:bg-surface-alt hover:text-text"
64
+ >
65
+ <HiOutlineXMark size={20} aria-hidden="true" />
66
+ </button>
67
+ <Button type="submit" loading={c.saving} disabled={c.saving} className="!w-auto">
68
+ Save
69
+ </Button>
70
+ </div>
71
+
72
+ <div className="flex flex-col gap-4 px-5 pb-5 pt-1">
73
+ {c.error && <Alert>{c.error}</Alert>}
74
+
75
+ <input
76
+ type="text"
77
+ aria-label="Title"
78
+ placeholder="Add title"
79
+ data-autofocus
80
+ className="w-full text-2xl bg-transparent text-text border-0 border-b-2 border-primary/50 focus:border-primary focus:outline-none pb-1 placeholder:text-text-muted"
81
+ value={values.title}
82
+ onChange={(e) => c.update({ title: e.target.value })}
83
+ />
84
+
85
+ {c.showEditScope && (
86
+ <fieldset className="flex flex-col gap-1.5 text-sm">
87
+ <legend className="text-xs font-bold uppercase tracking-wide text-text-muted mb-1">Apply changes to</legend>
88
+ <label className="flex items-center gap-2">
89
+ <input
90
+ type="radio"
91
+ name="event-edit-scope"
92
+ checked={c.editScope === "occurrence"}
93
+ onChange={() => c.setEditScope("occurrence")}
94
+ />
95
+ This event only
96
+ </label>
97
+ <label className="flex items-center gap-2">
98
+ <input
99
+ type="radio"
100
+ name="event-edit-scope"
101
+ checked={c.editScope === "series"}
102
+ onChange={() => c.setEditScope("series")}
103
+ />
104
+ The entire series
105
+ </label>
106
+ </fieldset>
107
+ )}
108
+
109
+ <DateTimeControls c={c} />
110
+
111
+ <div className="grid gap-x-8 gap-y-4 md:grid-cols-[minmax(0,1fr)_minmax(0,18rem)]">
112
+ <div className="flex flex-col gap-3 min-w-0">
113
+ <div role="tablist" aria-label="Event sections" className="flex gap-5 border-b border-border">
114
+ {TABS.map(({ tab: id, label }) => (
115
+ <button
116
+ key={id}
117
+ ref={(element) => {
118
+ tabButtons.current[id] = element;
119
+ }}
120
+ type="button"
121
+ role="tab"
122
+ id={`event-tab-${id}`}
123
+ aria-selected={tab === id}
124
+ aria-controls={`event-panel-${id}`}
125
+ tabIndex={tab === id ? 0 : -1}
126
+ onClick={() => setTab(id)}
127
+ onKeyDown={handleTabKeyDown}
128
+ className={[
129
+ "pb-2 -mb-px text-sm font-medium border-b-2",
130
+ tab === id ? "border-primary text-primary-dark" : "border-transparent text-text-muted hover:text-text",
131
+ ].join(" ")}
132
+ >
133
+ {label}
134
+ </button>
135
+ ))}
136
+ </div>
137
+
138
+ {tab === "find" && (
139
+ <div role="tabpanel" id="event-panel-find" aria-labelledby="event-tab-find" className="min-w-0">
140
+ <FindATime c={c} />
141
+ </div>
142
+ )}
143
+ <div role="tabpanel" id="event-panel-details" aria-labelledby="event-tab-details" hidden={tab !== "details"} className={tab === "details" ? "flex flex-col gap-3 min-w-0" : "hidden"}>
144
+ <VideoConferencingRow c={c} />
145
+ <LocationRow c={c} />
146
+ <DescriptionRow c={c} collapsible={false} />
147
+ <ReminderRow value={values.reminderMinutes} onChange={(minutes) => c.update({ reminderMinutes: minutes })} />
148
+ <IconRow icon={<HiOutlineCalendarDays size={20} />}>
149
+ <CalendarField c={c} />
150
+ </IconRow>
151
+ <IconRow icon={<HiOutlineBriefcase size={20} />}>
152
+ <div className="flex flex-col gap-2">
153
+ <select
154
+ id="event-busyStatus"
155
+ aria-label="Busy status"
156
+ className={`${INPUT_CLASS} !w-auto self-start`}
157
+ value={values.busyStatus}
158
+ onChange={(e) => c.update({ busyStatus: e.target.value as BusyStatus })}
159
+ >
160
+ {BUSY_STATUSES.map((status) => (
161
+ <option key={status} value={status}>
162
+ {BUSY_STATUS_LABEL[status]}
163
+ </option>
164
+ ))}
165
+ </select>
166
+ <VisibilitySelect c={c} />
167
+ </div>
168
+ </IconRow>
169
+
170
+ <div className="pl-8">
171
+ <label className="flex items-center gap-2 text-sm font-medium">
172
+ <input
173
+ type="checkbox"
174
+ checked={values.autoReplyEnabled}
175
+ onChange={(e) => c.update({ autoReplyEnabled: e.target.checked })}
176
+ />
177
+ Send an automatic reply while this event is happening
178
+ </label>
179
+ <p className="text-xs text-text-muted mt-1">
180
+ Applies in addition to your mailbox&rsquo;s own Automatic Replies setting (see Settings) &mdash; this
181
+ event&rsquo;s message takes over for its own start/end window.
182
+ </p>
183
+ {values.autoReplyEnabled && (
184
+ <textarea
185
+ aria-label="Automatic reply message"
186
+ className={`${INPUT_CLASS} mt-2`}
187
+ rows={3}
188
+ value={values.autoReplyMessage}
189
+ onChange={(e) => c.update({ autoReplyMessage: e.target.value })}
190
+ placeholder="I'm out of office and back on..."
191
+ />
192
+ )}
193
+ </div>
194
+ </div>
195
+ </div>
196
+
197
+ <section aria-labelledby="event-guests-heading" className="flex flex-col gap-4 min-w-0">
198
+ <div className="flex flex-col gap-2">
199
+ <h3 id="event-guests-heading" className="text-sm font-semibold">
200
+ Guests
201
+ </h3>
202
+ <GuestsField c={c} compact={false} />
203
+ </div>
204
+ <GuestPermissions c={c} />
205
+ </section>
206
+ </div>
207
+ </div>
208
+ </form>
209
+ );
210
+ }