@symbiote-native/calendar 0.1.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 (141) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +189 -0
  3. package/build/angular/index.d.ts +3 -0
  4. package/build/angular/index.js +3 -0
  5. package/build/angular/services/calendar-permissions.service/index.d.ts +5 -0
  6. package/build/angular/services/calendar-permissions.service/index.js +60 -0
  7. package/build/angular/services/reminders-permissions.service/index.d.ts +5 -0
  8. package/build/angular/services/reminders-permissions.service/index.js +60 -0
  9. package/build/core/attendee.d.ts +9 -0
  10. package/build/core/attendee.js +28 -0
  11. package/build/core/calendar-permission-api.d.ts +9 -0
  12. package/build/core/calendar-permission-api.js +9 -0
  13. package/build/core/calendar.d.ts +34 -0
  14. package/build/core/calendar.js +118 -0
  15. package/build/core/enums.d.ts +141 -0
  16. package/build/core/enums.js +157 -0
  17. package/build/core/event.d.ts +14 -0
  18. package/build/core/event.js +40 -0
  19. package/build/core/index.d.ts +6 -0
  20. package/build/core/index.js +6 -0
  21. package/build/core/native-module.d.ts +154 -0
  22. package/build/core/native-module.js +3 -0
  23. package/build/core/reminder.d.ts +10 -0
  24. package/build/core/reminder.js +34 -0
  25. package/build/core/types.d.ts +184 -0
  26. package/build/core/types.js +1 -0
  27. package/build/core/utils.d.ts +7 -0
  28. package/build/core/utils.js +29 -0
  29. package/build/legacy/calendar.d.ts +23 -0
  30. package/build/legacy/calendar.js +261 -0
  31. package/build/legacy/enums.d.ts +1 -0
  32. package/build/legacy/enums.js +2 -0
  33. package/build/legacy/index.d.ts +5 -0
  34. package/build/legacy/index.js +5 -0
  35. package/build/legacy/native-module.d.ts +39 -0
  36. package/build/legacy/native-module.js +3 -0
  37. package/build/legacy/permissions.d.ts +9 -0
  38. package/build/legacy/permissions.js +33 -0
  39. package/build/legacy/reminders.d.ts +6 -0
  40. package/build/legacy/reminders.js +56 -0
  41. package/build/legacy/types.d.ts +147 -0
  42. package/build/legacy/types.js +1 -0
  43. package/build/react/index.d.ts +3 -0
  44. package/build/react/index.js +3 -0
  45. package/build/react/use-calendar-permissions.d.ts +10 -0
  46. package/build/react/use-calendar-permissions.js +7 -0
  47. package/build/react/use-reminders-permissions.d.ts +8 -0
  48. package/build/react/use-reminders-permissions.js +10 -0
  49. package/build/solid/index.d.ts +3 -0
  50. package/build/solid/index.js +3 -0
  51. package/build/solid/use-calendar-permissions.d.ts +11 -0
  52. package/build/solid/use-calendar-permissions.js +7 -0
  53. package/build/solid/use-reminders-permissions.d.ts +9 -0
  54. package/build/solid/use-reminders-permissions.js +10 -0
  55. package/build/svelte/index.d.ts +3 -0
  56. package/build/svelte/index.js +3 -0
  57. package/build/svelte/use-calendar-permissions.svelte.d.ts +10 -0
  58. package/build/svelte/use-calendar-permissions.svelte.js +7 -0
  59. package/build/svelte/use-reminders-permissions.svelte.d.ts +8 -0
  60. package/build/svelte/use-reminders-permissions.svelte.js +10 -0
  61. package/build/vue/index.d.ts +3 -0
  62. package/build/vue/index.js +3 -0
  63. package/build/vue/use-calendar-permissions.d.ts +11 -0
  64. package/build/vue/use-calendar-permissions.js +7 -0
  65. package/build/vue/use-reminders-permissions.d.ts +9 -0
  66. package/build/vue/use-reminders-permissions.js +10 -0
  67. package/build-ngc/angular/index.d.ts +3 -0
  68. package/build-ngc/angular/index.js +4 -0
  69. package/build-ngc/angular/index.js.map +1 -0
  70. package/build-ngc/angular/services/calendar-permissions.service/index.d.ts +8 -0
  71. package/build-ngc/angular/services/calendar-permissions.service/index.js +17 -0
  72. package/build-ngc/angular/services/calendar-permissions.service/index.js.map +1 -0
  73. package/build-ngc/angular/services/reminders-permissions.service/index.d.ts +8 -0
  74. package/build-ngc/angular/services/reminders-permissions.service/index.js +17 -0
  75. package/build-ngc/angular/services/reminders-permissions.service/index.js.map +1 -0
  76. package/build-ngc/core/attendee.d.ts +9 -0
  77. package/build-ngc/core/attendee.js +29 -0
  78. package/build-ngc/core/attendee.js.map +1 -0
  79. package/build-ngc/core/calendar-permission-api.d.ts +9 -0
  80. package/build-ngc/core/calendar-permission-api.js +10 -0
  81. package/build-ngc/core/calendar-permission-api.js.map +1 -0
  82. package/build-ngc/core/calendar.d.ts +34 -0
  83. package/build-ngc/core/calendar.js +119 -0
  84. package/build-ngc/core/calendar.js.map +1 -0
  85. package/build-ngc/core/enums.d.ts +141 -0
  86. package/build-ngc/core/enums.js +158 -0
  87. package/build-ngc/core/enums.js.map +1 -0
  88. package/build-ngc/core/event.d.ts +14 -0
  89. package/build-ngc/core/event.js +41 -0
  90. package/build-ngc/core/event.js.map +1 -0
  91. package/build-ngc/core/index.d.ts +6 -0
  92. package/build-ngc/core/index.js +7 -0
  93. package/build-ngc/core/index.js.map +1 -0
  94. package/build-ngc/core/native-module.d.ts +154 -0
  95. package/build-ngc/core/native-module.js +4 -0
  96. package/build-ngc/core/native-module.js.map +1 -0
  97. package/build-ngc/core/reminder.d.ts +10 -0
  98. package/build-ngc/core/reminder.js +35 -0
  99. package/build-ngc/core/reminder.js.map +1 -0
  100. package/build-ngc/core/types.d.ts +184 -0
  101. package/build-ngc/core/types.js +2 -0
  102. package/build-ngc/core/types.js.map +1 -0
  103. package/build-ngc/core/utils.d.ts +7 -0
  104. package/build-ngc/core/utils.js +30 -0
  105. package/build-ngc/core/utils.js.map +1 -0
  106. package/native-link.json +29 -0
  107. package/package.json +155 -0
  108. package/src/angular/index.ts +3 -0
  109. package/src/angular/services/calendar-permissions.service/index.ts +19 -0
  110. package/src/angular/services/reminders-permissions.service/index.ts +16 -0
  111. package/src/core/attendee.ts +43 -0
  112. package/src/core/calendar-permission-api.ts +16 -0
  113. package/src/core/calendar.ts +197 -0
  114. package/src/core/enums.ts +156 -0
  115. package/src/core/event.ts +70 -0
  116. package/src/core/index.ts +18 -0
  117. package/src/core/native-module.ts +212 -0
  118. package/src/core/reminder.ts +52 -0
  119. package/src/core/types.ts +209 -0
  120. package/src/core/utils.ts +39 -0
  121. package/src/legacy/calendar.ts +401 -0
  122. package/src/legacy/enums.ts +2 -0
  123. package/src/legacy/index.ts +5 -0
  124. package/src/legacy/native-module.ts +77 -0
  125. package/src/legacy/permissions.ts +47 -0
  126. package/src/legacy/reminders.ts +98 -0
  127. package/src/legacy/types.ts +183 -0
  128. package/src/react/index.ts +3 -0
  129. package/src/react/use-calendar-permissions.ts +25 -0
  130. package/src/react/use-reminders-permissions.ts +25 -0
  131. package/src/solid/index.ts +3 -0
  132. package/src/solid/use-calendar-permissions.ts +26 -0
  133. package/src/solid/use-reminders-permissions.ts +26 -0
  134. package/src/svelte/index.ts +3 -0
  135. package/src/svelte/svelte-ambient.d.ts +3 -0
  136. package/src/svelte/svelte-compile.test-helper.ts +7 -0
  137. package/src/svelte/use-calendar-permissions.svelte.ts +25 -0
  138. package/src/svelte/use-reminders-permissions.svelte.ts +25 -0
  139. package/src/vue/index.ts +3 -0
  140. package/src/vue/use-calendar-permissions.ts +26 -0
  141. package/src/vue/use-reminders-permissions.ts +26 -0
@@ -0,0 +1,401 @@
1
+ import { Platform, UnavailabilityError } from 'expo-modules-core';
2
+ import { expoCalendar } from './native-module';
3
+ import type {
4
+ IAttendee,
5
+ ICalendar,
6
+ ICalendarDialogParams,
7
+ IDialogEventResult,
8
+ IEvent,
9
+ IOpenEventDialogResult,
10
+ IOpenEventPresentationOptions,
11
+ IPresentationOptions,
12
+ IRecurringEventOptions,
13
+ ISource,
14
+ } from './types';
15
+ import { stringifyDateValues, stringifyIfDate } from '../core/utils';
16
+
17
+ export async function createEventInCalendarAsync(
18
+ eventData: Omit<Partial<IEvent>, 'id'> = {},
19
+ presentationOptions?: IPresentationOptions,
20
+ ): Promise<IDialogEventResult> {
21
+ if (!expoCalendar.createEventInCalendarAsync) {
22
+ throw new UnavailabilityError('Calendar', 'createEventInCalendarAsync');
23
+ }
24
+ if ('id' in eventData && eventData.id) {
25
+ console.warn(
26
+ 'You attempted to create an event with an id. Event ids are assigned by the system.',
27
+ );
28
+ }
29
+ const params = { ...stringifyDateValues(eventData), ...presentationOptions };
30
+ return expoCalendar.createEventInCalendarAsync(params);
31
+ }
32
+
33
+ export async function openEventInCalendarAsync(
34
+ params: ICalendarDialogParams,
35
+ presentationOptions?: IOpenEventPresentationOptions,
36
+ ): Promise<IOpenEventDialogResult> {
37
+ if (!expoCalendar.openEventInCalendarAsync) {
38
+ throw new UnavailabilityError('Calendar', 'openEventInCalendarAsync');
39
+ }
40
+ if (!params.id) {
41
+ throw new Error(
42
+ 'openEventInCalendarAsync must be called with an id (string) of the target event',
43
+ );
44
+ }
45
+ return expoCalendar.openEventInCalendarAsync({
46
+ ...params,
47
+ ...presentationOptions,
48
+ });
49
+ }
50
+
51
+ export async function editEventInCalendarAsync(
52
+ params: ICalendarDialogParams,
53
+ presentationOptions?: IPresentationOptions,
54
+ ): Promise<IDialogEventResult> {
55
+ if (!expoCalendar.editEventInCalendarAsync) {
56
+ throw new UnavailabilityError('Calendar', 'editEventInCalendarAsync');
57
+ }
58
+ if (!params.id) {
59
+ throw new Error(
60
+ 'editEventInCalendarAsync must be called with an id (string) of the target event',
61
+ );
62
+ }
63
+ return expoCalendar.editEventInCalendarAsync({
64
+ ...params,
65
+ ...presentationOptions,
66
+ });
67
+ }
68
+
69
+ export async function isAvailableAsync(): Promise<boolean> {
70
+ return !!expoCalendar.getCalendarsAsync;
71
+ }
72
+
73
+ export async function getCalendarsAsync(
74
+ entityType?: string,
75
+ ): Promise<ICalendar[]> {
76
+ if (!expoCalendar.getCalendarsAsync) {
77
+ throw new UnavailabilityError('Calendar', 'getCalendarsAsync');
78
+ }
79
+ return expoCalendar.getCalendarsAsync(entityType ?? null);
80
+ }
81
+
82
+ export async function createCalendarAsync(
83
+ details: Partial<ICalendar> = {},
84
+ ): Promise<string> {
85
+ if (!expoCalendar.saveCalendarAsync) {
86
+ throw new UnavailabilityError('Calendar', 'createCalendarAsync');
87
+ }
88
+ const newDetails = { ...details, id: undefined };
89
+ return expoCalendar.saveCalendarAsync(stringifyDateValues(newDetails));
90
+ }
91
+
92
+ const ANDROID_READ_ONLY_CALENDAR_FIELDS = [
93
+ 'source',
94
+ 'color',
95
+ 'allowsModifications',
96
+ 'allowedAvailabilities',
97
+ 'isPrimary',
98
+ 'ownerAccount',
99
+ 'timeZone',
100
+ 'allowedReminders',
101
+ 'allowedAttendeeTypes',
102
+ 'accessLevel',
103
+ ];
104
+ const IOS_READ_ONLY_CALENDAR_FIELDS = [
105
+ 'source',
106
+ 'type',
107
+ 'entityType',
108
+ 'allowsModifications',
109
+ 'allowedAvailabilities',
110
+ ];
111
+
112
+ export async function updateCalendarAsync(
113
+ id: string,
114
+ details: Partial<ICalendar> = {},
115
+ ): Promise<string> {
116
+ if (!expoCalendar.saveCalendarAsync) {
117
+ throw new UnavailabilityError('Calendar', 'updateCalendarAsync');
118
+ }
119
+ if (!id) {
120
+ throw new Error(
121
+ 'updateCalendarAsync must be called with an id (string) of the target calendar',
122
+ );
123
+ }
124
+ const readOnlyFields =
125
+ Platform.OS === 'android'
126
+ ? ANDROID_READ_ONLY_CALENDAR_FIELDS
127
+ : IOS_READ_ONLY_CALENDAR_FIELDS;
128
+ if (readOnlyFields.some(field => Object.hasOwn(details, field))) {
129
+ console.warn(
130
+ 'updateCalendarAsync was called with one or more read-only properties, which will not be updated',
131
+ );
132
+ }
133
+ const newDetails = { ...details, id };
134
+ return expoCalendar.saveCalendarAsync(stringifyDateValues(newDetails));
135
+ }
136
+
137
+ export async function deleteCalendarAsync(id: string): Promise<void> {
138
+ if (!expoCalendar.deleteCalendarAsync) {
139
+ throw new UnavailabilityError('Calendar', 'deleteCalendarAsync');
140
+ }
141
+ if (!id) {
142
+ throw new Error(
143
+ 'deleteCalendarAsync must be called with an id (string) of the target calendar',
144
+ );
145
+ }
146
+ return expoCalendar.deleteCalendarAsync(id);
147
+ }
148
+
149
+ export async function getEventsAsync(
150
+ calendarIds: string[],
151
+ startDate: Date,
152
+ endDate: Date,
153
+ ): Promise<IEvent[]> {
154
+ if (!expoCalendar.getEventsAsync) {
155
+ throw new UnavailabilityError('Calendar', 'getEventsAsync');
156
+ }
157
+ if (!startDate) {
158
+ throw new Error(
159
+ 'getEventsAsync must be called with a startDate (date) to search for events',
160
+ );
161
+ }
162
+ if (!endDate) {
163
+ throw new Error(
164
+ 'getEventsAsync must be called with an endDate (date) to search for events',
165
+ );
166
+ }
167
+ if (!calendarIds || !calendarIds.length) {
168
+ throw new Error(
169
+ 'getEventsAsync must be called with a non-empty array of calendarIds to search',
170
+ );
171
+ }
172
+ return expoCalendar.getEventsAsync(
173
+ stringifyIfDate(startDate),
174
+ stringifyIfDate(endDate),
175
+ calendarIds,
176
+ );
177
+ }
178
+
179
+ export async function getEventAsync(
180
+ id: string,
181
+ recurringEventOptions: IRecurringEventOptions = {},
182
+ ): Promise<IEvent> {
183
+ if (!expoCalendar.getEventByIdAsync) {
184
+ throw new UnavailabilityError('Calendar', 'getEventAsync');
185
+ }
186
+ if (!id) {
187
+ throw new Error(
188
+ 'getEventAsync must be called with an id (string) of the target event',
189
+ );
190
+ }
191
+ if (Platform.OS === 'ios') {
192
+ return expoCalendar.getEventByIdAsync(
193
+ id,
194
+ recurringEventOptions.instanceStartDate,
195
+ );
196
+ }
197
+ return expoCalendar.getEventByIdAsync(id);
198
+ }
199
+
200
+ export async function createEventAsync(
201
+ calendarId: string,
202
+ eventData: Omit<Partial<IEvent>, 'id' | 'organizer'> = {},
203
+ ): Promise<string> {
204
+ if (!expoCalendar.saveEventAsync) {
205
+ throw new UnavailabilityError('Calendar', 'createEventAsync');
206
+ }
207
+ if (!calendarId) {
208
+ throw new Error(
209
+ 'createEventAsync must be called with an id (string) of the target calendar',
210
+ );
211
+ }
212
+ if ('id' in eventData && eventData.id) {
213
+ console.warn(
214
+ 'You attempted to create an event with an id. Event ids are assigned by the system.',
215
+ );
216
+ }
217
+ if (Platform.OS === 'android') {
218
+ if (!eventData.startDate) {
219
+ throw new Error('createEventAsync requires a startDate (Date)');
220
+ }
221
+ if (!eventData.endDate) {
222
+ throw new Error('createEventAsync requires an endDate (Date)');
223
+ }
224
+ }
225
+ return expoCalendar.saveEventAsync(
226
+ stringifyDateValues({ ...eventData, calendarId }),
227
+ {},
228
+ );
229
+ }
230
+
231
+ const IOS_READ_ONLY_EVENT_FIELDS = [
232
+ 'creationDate',
233
+ 'lastModifiedDate',
234
+ 'originalStartDate',
235
+ 'isDetached',
236
+ 'status',
237
+ 'organizer',
238
+ ];
239
+
240
+ export async function updateEventAsync(
241
+ id: string,
242
+ details: Omit<Partial<IEvent>, 'id'> = {},
243
+ recurringEventOptions: IRecurringEventOptions = {},
244
+ ): Promise<string> {
245
+ if (!expoCalendar.saveEventAsync) {
246
+ throw new UnavailabilityError('Calendar', 'updateEventAsync');
247
+ }
248
+ if (!id) {
249
+ throw new Error(
250
+ 'updateEventAsync must be called with an id (string) of the target event',
251
+ );
252
+ }
253
+ if (
254
+ Platform.OS === 'ios' &&
255
+ IOS_READ_ONLY_EVENT_FIELDS.some(field => Object.hasOwn(details, field))
256
+ ) {
257
+ console.warn(
258
+ 'updateEventAsync was called with one or more read-only properties, which will not be updated',
259
+ );
260
+ }
261
+ const { futureEvents = false, instanceStartDate } = recurringEventOptions;
262
+ const newDetails = { ...details, id, instanceStartDate };
263
+ return expoCalendar.saveEventAsync(stringifyDateValues(newDetails), {
264
+ futureEvents,
265
+ });
266
+ }
267
+
268
+ export async function deleteEventAsync(
269
+ id: string,
270
+ recurringEventOptions: IRecurringEventOptions = {},
271
+ ): Promise<void> {
272
+ if (!expoCalendar.deleteEventAsync) {
273
+ throw new UnavailabilityError('Calendar', 'deleteEventAsync');
274
+ }
275
+ if (!id) {
276
+ throw new Error(
277
+ 'deleteEventAsync must be called with an id (string) of the target event',
278
+ );
279
+ }
280
+ const { futureEvents = false, instanceStartDate } = recurringEventOptions;
281
+ return expoCalendar.deleteEventAsync(
282
+ { id, instanceStartDate },
283
+ { futureEvents },
284
+ );
285
+ }
286
+
287
+ export async function getAttendeesForEventAsync(
288
+ id: string,
289
+ recurringEventOptions: IRecurringEventOptions = {},
290
+ ): Promise<IAttendee[]> {
291
+ if (!expoCalendar.getAttendeesForEventAsync) {
292
+ throw new UnavailabilityError('Calendar', 'getAttendeesForEventAsync');
293
+ }
294
+ if (!id) {
295
+ throw new Error(
296
+ 'getAttendeesForEventAsync must be called with an id (string) of the target event',
297
+ );
298
+ }
299
+ const { instanceStartDate } = recurringEventOptions;
300
+ const params = Platform.OS === 'ios' ? { id, instanceStartDate } : id;
301
+ return expoCalendar.getAttendeesForEventAsync(params);
302
+ }
303
+
304
+ export async function createAttendeeAsync(
305
+ eventId: string,
306
+ details: Partial<IAttendee> = {},
307
+ ): Promise<string> {
308
+ if (!expoCalendar.saveAttendeeForEventAsync) {
309
+ throw new UnavailabilityError('Calendar', 'createAttendeeAsync');
310
+ }
311
+ if (!eventId) {
312
+ throw new Error(
313
+ 'createAttendeeAsync must be called with an id (string) of the target event',
314
+ );
315
+ }
316
+ if (!details.email) {
317
+ throw new Error('createAttendeeAsync requires an email (string)');
318
+ }
319
+ if (!details.role) {
320
+ throw new Error('createAttendeeAsync requires a role (string)');
321
+ }
322
+ if (!details.type) {
323
+ throw new Error('createAttendeeAsync requires a type (string)');
324
+ }
325
+ if (!details.status) {
326
+ throw new Error('createAttendeeAsync requires a status (string)');
327
+ }
328
+ return expoCalendar.saveAttendeeForEventAsync(
329
+ { ...details, id: undefined },
330
+ eventId,
331
+ );
332
+ }
333
+
334
+ export async function updateAttendeeAsync(
335
+ id: string,
336
+ details: Partial<IAttendee> = {},
337
+ ): Promise<string> {
338
+ if (!expoCalendar.saveAttendeeForEventAsync) {
339
+ throw new UnavailabilityError('Calendar', 'updateAttendeeAsync');
340
+ }
341
+ if (!id) {
342
+ throw new Error(
343
+ 'updateAttendeeAsync must be called with an id (string) of the target event',
344
+ );
345
+ }
346
+ return expoCalendar.saveAttendeeForEventAsync({ ...details, id }, null);
347
+ }
348
+
349
+ export async function deleteAttendeeAsync(id: string): Promise<void> {
350
+ if (!expoCalendar.deleteAttendeeAsync) {
351
+ throw new UnavailabilityError('Calendar', 'deleteAttendeeAsync');
352
+ }
353
+ if (!id) {
354
+ throw new Error(
355
+ 'deleteAttendeeAsync must be called with an id (string) of the target event',
356
+ );
357
+ }
358
+ return expoCalendar.deleteAttendeeAsync(id);
359
+ }
360
+
361
+ export async function getDefaultCalendarAsync(): Promise<ICalendar> {
362
+ if (!expoCalendar.getDefaultCalendarAsync) {
363
+ throw new UnavailabilityError('Calendar', 'getDefaultCalendarAsync');
364
+ }
365
+ return expoCalendar.getDefaultCalendarAsync();
366
+ }
367
+
368
+ export async function getSourcesAsync(): Promise<ISource[]> {
369
+ if (!expoCalendar.getSourcesAsync) {
370
+ throw new UnavailabilityError('Calendar', 'getSourcesAsync');
371
+ }
372
+ return expoCalendar.getSourcesAsync();
373
+ }
374
+
375
+ export async function getSourceAsync(id: string): Promise<ISource> {
376
+ if (!expoCalendar.getSourceByIdAsync) {
377
+ throw new UnavailabilityError('Calendar', 'getSourceAsync');
378
+ }
379
+ if (!id) {
380
+ throw new Error(
381
+ 'getSourceAsync must be called with an id (string) of the target source',
382
+ );
383
+ }
384
+ return expoCalendar.getSourceByIdAsync(id);
385
+ }
386
+
387
+ /** @platform android */
388
+ export function openEventInCalendar(id: string): void {
389
+ if (!expoCalendar.openEventInCalendar) {
390
+ console.warn(
391
+ `openEventInCalendar is not available on platform: ${Platform.OS}`,
392
+ );
393
+ return;
394
+ }
395
+ if (!id) {
396
+ throw new Error(
397
+ 'openEventInCalendar must be called with an id (string) of the target event',
398
+ );
399
+ }
400
+ return expoCalendar.openEventInCalendar(id);
401
+ }
@@ -0,0 +1,2 @@
1
+ // Same enum value sets as upstream's legacy/Calendar.ts and next Calendar.ts share one source.
2
+ export * from '../core/enums';
@@ -0,0 +1,5 @@
1
+ export * from './enums';
2
+ export * from './types';
3
+ export * from './calendar';
4
+ export * from './permissions';
5
+ export * from './reminders';
@@ -0,0 +1,77 @@
1
+ import { requireNativeModule } from 'expo-modules-core';
2
+ import type {
3
+ IAttendee,
4
+ ICalendar,
5
+ ICalendarDialogParams,
6
+ IDialogEventResult,
7
+ IEvent,
8
+ IOpenEventDialogResult,
9
+ IOpenEventPresentationOptions,
10
+ IPresentationOptions,
11
+ IReminder,
12
+ ISource,
13
+ PermissionResponse,
14
+ } from './types';
15
+
16
+ const EXPO_CALENDAR_MODULE_NAME = 'ExpoCalendar';
17
+
18
+ export type INativeCalendarModule = {
19
+ createEventInCalendarAsync?(
20
+ params: Record<string, unknown>,
21
+ ): Promise<IDialogEventResult>;
22
+ openEventInCalendarAsync?(
23
+ params: ICalendarDialogParams & IOpenEventPresentationOptions,
24
+ ): Promise<IOpenEventDialogResult>;
25
+ editEventInCalendarAsync?(
26
+ params: ICalendarDialogParams & IPresentationOptions,
27
+ ): Promise<IDialogEventResult>;
28
+ getCalendarsAsync?(entityType: string | null): Promise<ICalendar[]>;
29
+ saveCalendarAsync?(details: Record<string, unknown>): Promise<string>;
30
+ deleteCalendarAsync?(id: string): Promise<void>;
31
+ getEventsAsync?(
32
+ startDate: string | Date,
33
+ endDate: string | Date,
34
+ calendarIds: string[],
35
+ ): Promise<IEvent[]>;
36
+ getEventByIdAsync?(
37
+ id: string,
38
+ instanceStartDate?: string | Date,
39
+ ): Promise<IEvent>;
40
+ saveEventAsync?(
41
+ details: Record<string, unknown>,
42
+ options: { futureEvents?: boolean },
43
+ ): Promise<string>;
44
+ deleteEventAsync?(
45
+ params: { id: string; instanceStartDate?: string | Date },
46
+ options: { futureEvents?: boolean },
47
+ ): Promise<void>;
48
+ getAttendeesForEventAsync?(
49
+ params: { id: string; instanceStartDate?: string | Date } | string,
50
+ ): Promise<IAttendee[]>;
51
+ saveAttendeeForEventAsync?(
52
+ details: Record<string, unknown>,
53
+ eventId: string | null,
54
+ ): Promise<string>;
55
+ deleteAttendeeAsync?(id: string): Promise<void>;
56
+ getDefaultCalendarAsync?(): Promise<ICalendar>;
57
+ getRemindersAsync?(
58
+ startDate: string | Date | null,
59
+ endDate: string | Date | null,
60
+ calendarIds: (string | null)[],
61
+ status: string | null,
62
+ ): Promise<IReminder[]>;
63
+ getReminderByIdAsync?(id: string): Promise<IReminder>;
64
+ saveReminderAsync?(details: Record<string, unknown>): Promise<string>;
65
+ deleteReminderAsync?(id: string): Promise<void>;
66
+ getSourcesAsync?(): Promise<ISource[]>;
67
+ getSourceByIdAsync?(id: string): Promise<ISource>;
68
+ openEventInCalendar?(id: string): void;
69
+ getCalendarPermissionsAsync?(): Promise<PermissionResponse>;
70
+ requestCalendarPermissionsAsync?(): Promise<PermissionResponse>;
71
+ getRemindersPermissionsAsync?(): Promise<PermissionResponse>;
72
+ requestRemindersPermissionsAsync?(): Promise<PermissionResponse>;
73
+ };
74
+
75
+ export const expoCalendar = requireNativeModule<INativeCalendarModule>(
76
+ EXPO_CALENDAR_MODULE_NAME,
77
+ );
@@ -0,0 +1,47 @@
1
+ import { UnavailabilityError } from 'expo-modules-core';
2
+ import { expoCalendar } from './native-module';
3
+ import type { PermissionResponse } from './types';
4
+
5
+ export async function getCalendarPermissionsAsync(): Promise<PermissionResponse> {
6
+ if (!expoCalendar.getCalendarPermissionsAsync) {
7
+ throw new UnavailabilityError('Calendar', 'getCalendarPermissionsAsync');
8
+ }
9
+ return expoCalendar.getCalendarPermissionsAsync();
10
+ }
11
+
12
+ /** @platform ios */
13
+ export async function getRemindersPermissionsAsync(): Promise<PermissionResponse> {
14
+ if (!expoCalendar.getRemindersPermissionsAsync) {
15
+ throw new UnavailabilityError('Calendar', 'getRemindersPermissionsAsync');
16
+ }
17
+ return expoCalendar.getRemindersPermissionsAsync();
18
+ }
19
+
20
+ export async function requestCalendarPermissionsAsync(): Promise<PermissionResponse> {
21
+ if (!expoCalendar.requestCalendarPermissionsAsync) {
22
+ throw new UnavailabilityError(
23
+ 'Calendar',
24
+ 'requestCalendarPermissionsAsync',
25
+ );
26
+ }
27
+ return expoCalendar.requestCalendarPermissionsAsync();
28
+ }
29
+
30
+ /** @deprecated Use `requestCalendarPermissionsAsync` instead */
31
+ export async function requestPermissionsAsync(): Promise<PermissionResponse> {
32
+ console.warn(
33
+ 'requestPermissionsAsync is deprecated. Use requestCalendarPermissionsAsync instead.',
34
+ );
35
+ return requestCalendarPermissionsAsync();
36
+ }
37
+
38
+ /** @platform ios */
39
+ export async function requestRemindersPermissionsAsync(): Promise<PermissionResponse> {
40
+ if (!expoCalendar.requestRemindersPermissionsAsync) {
41
+ throw new UnavailabilityError(
42
+ 'Calendar',
43
+ 'requestRemindersPermissionsAsync',
44
+ );
45
+ }
46
+ return expoCalendar.requestRemindersPermissionsAsync();
47
+ }
@@ -0,0 +1,98 @@
1
+ import { UnavailabilityError } from 'expo-modules-core';
2
+ import { expoCalendar } from './native-module';
3
+ import type { IReminder } from './types';
4
+ import { stringifyDateValues, stringifyIfDate } from '../core/utils';
5
+
6
+ export async function getRemindersAsync(
7
+ calendarIds: (string | null)[],
8
+ status: string | null,
9
+ startDate: Date | null,
10
+ endDate: Date | null,
11
+ ): Promise<IReminder[]> {
12
+ if (!expoCalendar.getRemindersAsync) {
13
+ throw new UnavailabilityError('Calendar', 'getRemindersAsync');
14
+ }
15
+ if (status && !startDate) {
16
+ throw new Error(
17
+ 'getRemindersAsync must be called with a startDate (date) to search for reminders',
18
+ );
19
+ }
20
+ if (status && !endDate) {
21
+ throw new Error(
22
+ 'getRemindersAsync must be called with an endDate (date) to search for reminders',
23
+ );
24
+ }
25
+ if (!calendarIds || !calendarIds.length) {
26
+ throw new Error(
27
+ 'getRemindersAsync must be called with a non-empty array of calendarIds to search',
28
+ );
29
+ }
30
+ return expoCalendar.getRemindersAsync(
31
+ startDate ? stringifyIfDate(startDate) : null,
32
+ endDate ? stringifyIfDate(endDate) : null,
33
+ calendarIds,
34
+ status,
35
+ );
36
+ }
37
+
38
+ export async function getReminderAsync(id: string): Promise<IReminder> {
39
+ if (!expoCalendar.getReminderByIdAsync) {
40
+ throw new UnavailabilityError('Calendar', 'getReminderAsync');
41
+ }
42
+ if (!id) {
43
+ throw new Error(
44
+ 'getReminderAsync must be called with an id (string) of the target reminder',
45
+ );
46
+ }
47
+ return expoCalendar.getReminderByIdAsync(id);
48
+ }
49
+
50
+ export async function createReminderAsync(
51
+ calendarId: string | null,
52
+ reminder: IReminder = {},
53
+ ): Promise<string> {
54
+ if (!expoCalendar.saveReminderAsync) {
55
+ throw new UnavailabilityError('Calendar', 'createReminderAsync');
56
+ }
57
+ const { id: _id, ...details } = reminder;
58
+ return expoCalendar.saveReminderAsync(
59
+ stringifyDateValues({ ...details, calendarId: calendarId ?? undefined }),
60
+ );
61
+ }
62
+
63
+ export async function updateReminderAsync(
64
+ id: string,
65
+ details: IReminder = {},
66
+ ): Promise<string> {
67
+ if (!expoCalendar.saveReminderAsync) {
68
+ throw new UnavailabilityError('Calendar', 'updateReminderAsync');
69
+ }
70
+ if (!id) {
71
+ throw new Error(
72
+ 'updateReminderAsync must be called with an id (string) of the target reminder',
73
+ );
74
+ }
75
+ if (
76
+ Object.hasOwn(details, 'creationDate') ||
77
+ Object.hasOwn(details, 'lastModifiedDate')
78
+ ) {
79
+ console.warn(
80
+ 'updateReminderAsync was called with one or more read-only properties, which will not be updated',
81
+ );
82
+ }
83
+ return expoCalendar.saveReminderAsync(
84
+ stringifyDateValues({ ...details, id }),
85
+ );
86
+ }
87
+
88
+ export async function deleteReminderAsync(id: string): Promise<void> {
89
+ if (!expoCalendar.deleteReminderAsync) {
90
+ throw new UnavailabilityError('Calendar', 'deleteReminderAsync');
91
+ }
92
+ if (!id) {
93
+ throw new Error(
94
+ 'deleteReminderAsync must be called with an id (string) of the target reminder',
95
+ );
96
+ }
97
+ return expoCalendar.deleteReminderAsync(id);
98
+ }