@ng-native/expo 0.18.0 → 0.18.2

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.
@@ -54,6 +54,17 @@ class KeyboardModule : Module() {
54
54
 
55
55
  Events("onKeyboardChange", "onKeyboardMove")
56
56
 
57
+ // How far below the top of the screen the app's window starts, in points: not zero in the
58
+ // lower half of a split screen or in a freeform window. React Native measures a view in the
59
+ // window and reports the keyboard's top on the screen. Read where it is compared, since the
60
+ // window can move.
61
+ Function("windowTopOnScreen") {
62
+ val decor = appContext.currentActivity?.window?.decorView ?: return@Function 0.0
63
+ val location = IntArray(2)
64
+ decor.getLocationOnScreen(location)
65
+ location[1] / decor.resources.displayMetrics.density.toDouble()
66
+ }
67
+
57
68
  OnStartObserving {
58
69
  observing = true
59
70
  watchActivity()
@@ -0,0 +1,99 @@
1
+ /**
2
+ * `Calendar`, bound to `expo-calendar`: the calendars on the device, and the events and reminders
3
+ * in them.
4
+ *
5
+ * ```ts
6
+ * import { Calendar } from '@ng-native/expo/calendar';
7
+ *
8
+ * private readonly calendar = inject(Calendar);
9
+ *
10
+ * async thisWeek(): Promise<ExpoCalendarEvent[]> {
11
+ * if (!(await this.calendar.permission.ensure())) return [];
12
+ * const calendars = await this.calendar.calendars();
13
+ * const start = new Date();
14
+ * const end = new Date(start.getTime() + 7 * 24 * 60 * 60 * 1000);
15
+ * return this.calendar.events(calendars, start, end);
16
+ * }
17
+ *
18
+ * async book(calendar: ExpoCalendar): Promise<void> {
19
+ * await calendar.createEvent({ title: 'Padel', startDate, endDate, alarms: [{ relativeOffset: -30 }] });
20
+ * }
21
+ * ```
22
+ *
23
+ * This is the module's object API: a calendar, an event, a reminder and an attendee are handles
24
+ * with their own `update()` and `delete()`, and a calendar makes its own events and reminders. The
25
+ * service is where the handles are reached from, so a test can provide them, and where the
26
+ * permissions are: full access to the calendars, the write-only access iOS 17 added for an app
27
+ * that only adds events, and on iOS the reminders.
28
+ *
29
+ * What exists on iOS alone - the default calendar, the calendar picker, the sources and the
30
+ * reminders - answers null, nothing or refused on Android rather than throwing, so code shared by
31
+ * both runs on both. Without the module installed, every list answers empty, every lookup null,
32
+ * and the permissions are refused.
33
+ */
34
+ import { InjectionToken } from '@angular/core';
35
+ import type { Availability as ExpoAvailability, EntityTypes as ExpoEntityTypes, ExpoCalendar, ExpoCalendarEvent, ExpoCalendarReminder, Frequency as ExpoFrequency, Source } from 'expo-calendar';
36
+ import { type ModulePlatform } from './native.ts';
37
+ import { Permission } from './permissions.ts';
38
+ import * as i0 from "@angular/core";
39
+ type Expo = typeof import('expo-calendar');
40
+ /** The module's functions and classes this service calls. A test provides fakes of each. */
41
+ export type NativeCalendar = Pick<Expo, 'getCalendarPermissions' | 'requestCalendarPermissions' | 'getRemindersPermissions' | 'requestRemindersPermissions' | 'getCalendars' | 'getDefaultCalendarSync' | 'createCalendar' | 'presentPicker' | 'listEvents' | 'getSourcesSync' | 'ExpoCalendar' | 'ExpoCalendarEvent' | 'ExpoCalendarReminder'>;
42
+ type Args<K extends keyof NativeCalendar> = NativeCalendar[K] extends (...args: infer A) => unknown ? A : never;
43
+ /**
44
+ * What a calendar holds, as `expo-calendar`'s own enum. Importing the enum from the module loads
45
+ * the module, which a test in Node cannot; these are the same strings, typed as the enum.
46
+ */
47
+ export declare const EntityTypes: typeof ExpoEntityTypes;
48
+ /** How often a recurrence rule repeats, as the module's own enum. */
49
+ export declare const Frequency: typeof ExpoFrequency;
50
+ /** Whether an event shows its time as taken, as the module's own enum. */
51
+ export declare const Availability: typeof ExpoAvailability;
52
+ export declare class Calendar {
53
+ /** Overridden in a test to read calendars that are not there. */
54
+ static readonly SOURCE: InjectionToken<NativeCalendar | null>;
55
+ /** Overridden in a test to be on iOS, where the calls only iOS has can be made. */
56
+ static readonly PLATFORM: InjectionToken<ModulePlatform | null>;
57
+ private readonly native;
58
+ private readonly platform;
59
+ /** Full access: reading the calendars and their events, as well as adding to them. */
60
+ readonly permission: Permission;
61
+ /**
62
+ * Write-only access, on iOS 17 and later: enough to add events, and nothing to read. Elsewhere
63
+ * the same as {@link permission}.
64
+ */
65
+ readonly writePermission: Permission;
66
+ /** The reminders, on iOS. Refused on Android, which keeps none in its calendars. */
67
+ readonly remindersPermission: Permission;
68
+ /**
69
+ * The calendars on the device, of events unless {@link EntityTypes.REMINDER} is asked for. The
70
+ * module itself lists both kinds when given none, and on iOS refuses that without reminders access.
71
+ */
72
+ calendars(entityType?: ExpoEntityTypes): Promise<ExpoCalendar[]>;
73
+ /** The calendar with this id, or null. */
74
+ calendar(id: string): Promise<ExpoCalendar | null>;
75
+ /** The calendar new events go in unless another is chosen, on iOS. Null on Android. */
76
+ defaultCalendar(): ExpoCalendar | null;
77
+ /** A new calendar, with the module's own details: `title`, `color`, `entityType` and the rest. */
78
+ createCalendar(...details: Args<'createCalendar'>): Promise<ExpoCalendar | null>;
79
+ /** On iOS, the system's calendar picker. Null if the user cancels it, and on Android. */
80
+ pickCalendar(): Promise<ExpoCalendar | null>;
81
+ /**
82
+ * The events from `start` to `end` in the calendars given, as handles or their ids, each
83
+ * occurrence of a recurring event as an event of its own. An event that overlaps the range at
84
+ * all is in it, one running across either end included.
85
+ */
86
+ events(calendars: readonly (string | ExpoCalendar)[], start: Date, end: Date): Promise<ExpoCalendarEvent[]>;
87
+ /** The event with this id, such as one kept from an earlier list, or null. */
88
+ event(id: string): Promise<ExpoCalendarEvent | null>;
89
+ /** The reminder with this id, on iOS, or null. */
90
+ reminder(id: string): Promise<ExpoCalendarReminder | null>;
91
+ /** The accounts the calendars belong to, on iOS: iCloud, Exchange, a subscription. */
92
+ sources(): Source[];
93
+ private calendarPermission;
94
+ /** The module is here and the app is on iOS, where the calls it has only there exist. */
95
+ private ios;
96
+ static ɵfac: i0.ɵɵFactoryDeclaration<Calendar, never>;
97
+ static ɵprov: i0.ɵɵInjectableDeclaration<any>;
98
+ }
99
+ export {};
@@ -0,0 +1,135 @@
1
+ /**
2
+ * `Calendar`, bound to `expo-calendar`: the calendars on the device, and the events and reminders
3
+ * in them.
4
+ *
5
+ * ```ts
6
+ * import { Calendar } from '@ng-native/expo/calendar';
7
+ *
8
+ * private readonly calendar = inject(Calendar);
9
+ *
10
+ * async thisWeek(): Promise<ExpoCalendarEvent[]> {
11
+ * if (!(await this.calendar.permission.ensure())) return [];
12
+ * const calendars = await this.calendar.calendars();
13
+ * const start = new Date();
14
+ * const end = new Date(start.getTime() + 7 * 24 * 60 * 60 * 1000);
15
+ * return this.calendar.events(calendars, start, end);
16
+ * }
17
+ *
18
+ * async book(calendar: ExpoCalendar): Promise<void> {
19
+ * await calendar.createEvent({ title: 'Padel', startDate, endDate, alarms: [{ relativeOffset: -30 }] });
20
+ * }
21
+ * ```
22
+ *
23
+ * This is the module's object API: a calendar, an event, a reminder and an attendee are handles
24
+ * with their own `update()` and `delete()`, and a calendar makes its own events and reminders. The
25
+ * service is where the handles are reached from, so a test can provide them, and where the
26
+ * permissions are: full access to the calendars, the write-only access iOS 17 added for an app
27
+ * that only adds events, and on iOS the reminders.
28
+ *
29
+ * What exists on iOS alone - the default calendar, the calendar picker, the sources and the
30
+ * reminders - answers null, nothing or refused on Android rather than throwing, so code shared by
31
+ * both runs on both. Without the module installed, every list answers empty, every lookup null,
32
+ * and the permissions are refused.
33
+ */
34
+ import { InjectionToken, Service, inject } from '@angular/core';
35
+ import { currentPlatform, expoModule } from "./native.js";
36
+ import { Permission, UNAVAILABLE } from "./permissions.js";
37
+ import * as i0 from "@angular/core";
38
+ /**
39
+ * What a calendar holds, as `expo-calendar`'s own enum. Importing the enum from the module loads
40
+ * the module, which a test in Node cannot; these are the same strings, typed as the enum.
41
+ */
42
+ export const EntityTypes = {
43
+ EVENT: 'event',
44
+ REMINDER: 'reminder',
45
+ };
46
+ /** How often a recurrence rule repeats, as the module's own enum. */
47
+ export const Frequency = {
48
+ DAILY: 'daily',
49
+ WEEKLY: 'weekly',
50
+ MONTHLY: 'monthly',
51
+ YEARLY: 'yearly',
52
+ };
53
+ /** Whether an event shows its time as taken, as the module's own enum. */
54
+ export const Availability = {
55
+ NOT_SUPPORTED: 'notSupported',
56
+ BUSY: 'busy',
57
+ FREE: 'free',
58
+ TENTATIVE: 'tentative',
59
+ UNAVAILABLE: 'unavailable',
60
+ };
61
+ export class Calendar {
62
+ /** Overridden in a test to read calendars that are not there. */
63
+ static SOURCE = new InjectionToken('angular-native.calendarSource', { factory: () => expoModule('expo-calendar', () => require('expo-calendar')) });
64
+ /** Overridden in a test to be on iOS, where the calls only iOS has can be made. */
65
+ static PLATFORM = new InjectionToken('angular-native.calendarPlatform', { factory: currentPlatform });
66
+ native = inject(Calendar.SOURCE);
67
+ platform = inject(Calendar.PLATFORM);
68
+ /** Full access: reading the calendars and their events, as well as adding to them. */
69
+ permission = this.calendarPermission(false);
70
+ /**
71
+ * Write-only access, on iOS 17 and later: enough to add events, and nothing to read. Elsewhere
72
+ * the same as {@link permission}.
73
+ */
74
+ writePermission = this.calendarPermission(true);
75
+ /** The reminders, on iOS. Refused on Android, which keeps none in its calendars. */
76
+ remindersPermission = Permission.of(() => (this.ios() ? this.native.getRemindersPermissions() : Promise.resolve(UNAVAILABLE)), () => (this.ios() ? this.native.requestRemindersPermissions() : Promise.resolve(UNAVAILABLE)));
77
+ /**
78
+ * The calendars on the device, of events unless {@link EntityTypes.REMINDER} is asked for. The
79
+ * module itself lists both kinds when given none, and on iOS refuses that without reminders access.
80
+ */
81
+ async calendars(entityType = EntityTypes.EVENT) {
82
+ return (await this.native?.getCalendars(entityType)) ?? [];
83
+ }
84
+ /** The calendar with this id, or null. */
85
+ async calendar(id) {
86
+ return (await this.native?.ExpoCalendar.get(id)) ?? null;
87
+ }
88
+ /** The calendar new events go in unless another is chosen, on iOS. Null on Android. */
89
+ defaultCalendar() {
90
+ return this.ios() ? this.native.getDefaultCalendarSync() : null;
91
+ }
92
+ /** A new calendar, with the module's own details: `title`, `color`, `entityType` and the rest. */
93
+ async createCalendar(...details) {
94
+ return (await this.native?.createCalendar(...details)) ?? null;
95
+ }
96
+ /** On iOS, the system's calendar picker. Null if the user cancels it, and on Android. */
97
+ async pickCalendar() {
98
+ return this.ios() ? this.native.presentPicker() : null;
99
+ }
100
+ /**
101
+ * The events from `start` to `end` in the calendars given, as handles or their ids, each
102
+ * occurrence of a recurring event as an event of its own. An event that overlaps the range at
103
+ * all is in it, one running across either end included.
104
+ */
105
+ async events(calendars, start, end) {
106
+ if (!this.native || calendars.length === 0)
107
+ return [];
108
+ return this.native.listEvents([...calendars], start, end);
109
+ }
110
+ /** The event with this id, such as one kept from an earlier list, or null. */
111
+ async event(id) {
112
+ return (await this.native?.ExpoCalendarEvent.get(id)) ?? null;
113
+ }
114
+ /** The reminder with this id, on iOS, or null. */
115
+ async reminder(id) {
116
+ return this.ios() ? this.native.ExpoCalendarReminder.get(id) : null;
117
+ }
118
+ /** The accounts the calendars belong to, on iOS: iCloud, Exchange, a subscription. */
119
+ sources() {
120
+ return this.ios() ? this.native.getSourcesSync() : [];
121
+ }
122
+ calendarPermission(writeOnly) {
123
+ return Permission.of(() => this.native?.getCalendarPermissions(writeOnly) ?? Promise.resolve(UNAVAILABLE), () => this.native?.requestCalendarPermissions(writeOnly) ?? Promise.resolve(UNAVAILABLE));
124
+ }
125
+ /** The module is here and the app is on iOS, where the calls it has only there exist. */
126
+ ios() {
127
+ return this.native !== null && this.platform === 'ios';
128
+ }
129
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: Calendar, deps: [], target: i0.ɵɵFactoryTarget.Service });
130
+ static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.2.0", ngImport: i0, type: Calendar });
131
+ }
132
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.0", ngImport: i0, type: Calendar, decorators: [{
133
+ type: Service
134
+ }] });
135
+ //# sourceMappingURL=calendar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar.js","sourceRoot":"","sources":["../src/calendar.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `Calendar`, bound to `expo-calendar`: the calendars on the device, and the events and reminders\n * in them.\n *\n * ```ts\n * import { Calendar } from '@ng-native/expo/calendar';\n *\n * private readonly calendar = inject(Calendar);\n *\n * async thisWeek(): Promise<ExpoCalendarEvent[]> {\n * if (!(await this.calendar.permission.ensure())) return [];\n * const calendars = await this.calendar.calendars();\n * const start = new Date();\n * const end = new Date(start.getTime() + 7 * 24 * 60 * 60 * 1000);\n * return this.calendar.events(calendars, start, end);\n * }\n *\n * async book(calendar: ExpoCalendar): Promise<void> {\n * await calendar.createEvent({ title: 'Padel', startDate, endDate, alarms: [{ relativeOffset: -30 }] });\n * }\n * ```\n *\n * This is the module's object API: a calendar, an event, a reminder and an attendee are handles\n * with their own `update()` and `delete()`, and a calendar makes its own events and reminders. The\n * service is where the handles are reached from, so a test can provide them, and where the\n * permissions are: full access to the calendars, the write-only access iOS 17 added for an app\n * that only adds events, and on iOS the reminders.\n *\n * What exists on iOS alone - the default calendar, the calendar picker, the sources and the\n * reminders - answers null, nothing or refused on Android rather than throwing, so code shared by\n * both runs on both. Without the module installed, every list answers empty, every lookup null,\n * and the permissions are refused.\n */\nimport { InjectionToken, Service, inject } from '@angular/core';\nimport type {\n Availability as ExpoAvailability,\n EntityTypes as ExpoEntityTypes,\n ExpoCalendar,\n ExpoCalendarEvent,\n ExpoCalendarReminder,\n Frequency as ExpoFrequency,\n Source,\n} from 'expo-calendar';\nimport { currentPlatform, expoModule, type ModulePlatform } from './native.ts';\nimport { Permission, UNAVAILABLE } from './permissions.ts';\n\ntype Expo = typeof import('expo-calendar');\n\n/** The module's functions and classes this service calls. A test provides fakes of each. */\nexport type NativeCalendar = Pick<\n Expo,\n | 'getCalendarPermissions'\n | 'requestCalendarPermissions'\n | 'getRemindersPermissions'\n | 'requestRemindersPermissions'\n | 'getCalendars'\n | 'getDefaultCalendarSync'\n | 'createCalendar'\n | 'presentPicker'\n | 'listEvents'\n | 'getSourcesSync'\n | 'ExpoCalendar'\n | 'ExpoCalendarEvent'\n | 'ExpoCalendarReminder'\n>;\n\ntype Args<K extends keyof NativeCalendar> = NativeCalendar[K] extends (...args: infer A) => unknown\n ? A\n : never;\n\n/**\n * What a calendar holds, as `expo-calendar`'s own enum. Importing the enum from the module loads\n * the module, which a test in Node cannot; these are the same strings, typed as the enum.\n */\nexport const EntityTypes = {\n EVENT: 'event',\n REMINDER: 'reminder',\n} as unknown as typeof ExpoEntityTypes;\n\n/** How often a recurrence rule repeats, as the module's own enum. */\nexport const Frequency = {\n DAILY: 'daily',\n WEEKLY: 'weekly',\n MONTHLY: 'monthly',\n YEARLY: 'yearly',\n} as unknown as typeof ExpoFrequency;\n\n/** Whether an event shows its time as taken, as the module's own enum. */\nexport const Availability = {\n NOT_SUPPORTED: 'notSupported',\n BUSY: 'busy',\n FREE: 'free',\n TENTATIVE: 'tentative',\n UNAVAILABLE: 'unavailable',\n} as unknown as typeof ExpoAvailability;\n\n@Service()\nexport class Calendar {\n /** Overridden in a test to read calendars that are not there. */\n static readonly SOURCE = new InjectionToken<NativeCalendar | null>(\n 'angular-native.calendarSource',\n { factory: () => expoModule('expo-calendar', () => require('expo-calendar') as Expo) },\n );\n\n /** Overridden in a test to be on iOS, where the calls only iOS has can be made. */\n static readonly PLATFORM = new InjectionToken<ModulePlatform | null>(\n 'angular-native.calendarPlatform',\n { factory: currentPlatform },\n );\n\n private readonly native = inject(Calendar.SOURCE);\n private readonly platform = inject(Calendar.PLATFORM);\n\n /** Full access: reading the calendars and their events, as well as adding to them. */\n readonly permission: Permission = this.calendarPermission(false);\n\n /**\n * Write-only access, on iOS 17 and later: enough to add events, and nothing to read. Elsewhere\n * the same as {@link permission}.\n */\n readonly writePermission: Permission = this.calendarPermission(true);\n\n /** The reminders, on iOS. Refused on Android, which keeps none in its calendars. */\n readonly remindersPermission: Permission = Permission.of(\n () => (this.ios() ? this.native!.getRemindersPermissions() : Promise.resolve(UNAVAILABLE)),\n () => (this.ios() ? this.native!.requestRemindersPermissions() : Promise.resolve(UNAVAILABLE)),\n );\n\n /**\n * The calendars on the device, of events unless {@link EntityTypes.REMINDER} is asked for. The\n * module itself lists both kinds when given none, and on iOS refuses that without reminders access.\n */\n async calendars(entityType: ExpoEntityTypes = EntityTypes.EVENT): Promise<ExpoCalendar[]> {\n return (await this.native?.getCalendars(entityType)) ?? [];\n }\n\n /** The calendar with this id, or null. */\n async calendar(id: string): Promise<ExpoCalendar | null> {\n return (await this.native?.ExpoCalendar.get(id)) ?? null;\n }\n\n /** The calendar new events go in unless another is chosen, on iOS. Null on Android. */\n defaultCalendar(): ExpoCalendar | null {\n return this.ios() ? this.native!.getDefaultCalendarSync() : null;\n }\n\n /** A new calendar, with the module's own details: `title`, `color`, `entityType` and the rest. */\n async createCalendar(...details: Args<'createCalendar'>): Promise<ExpoCalendar | null> {\n return (await this.native?.createCalendar(...details)) ?? null;\n }\n\n /** On iOS, the system's calendar picker. Null if the user cancels it, and on Android. */\n async pickCalendar(): Promise<ExpoCalendar | null> {\n return this.ios() ? this.native!.presentPicker() : null;\n }\n\n /**\n * The events from `start` to `end` in the calendars given, as handles or their ids, each\n * occurrence of a recurring event as an event of its own. An event that overlaps the range at\n * all is in it, one running across either end included.\n */\n async events(\n calendars: readonly (string | ExpoCalendar)[],\n start: Date,\n end: Date,\n ): Promise<ExpoCalendarEvent[]> {\n if (!this.native || calendars.length === 0) return [];\n return this.native.listEvents([...calendars], start, end);\n }\n\n /** The event with this id, such as one kept from an earlier list, or null. */\n async event(id: string): Promise<ExpoCalendarEvent | null> {\n return (await this.native?.ExpoCalendarEvent.get(id)) ?? null;\n }\n\n /** The reminder with this id, on iOS, or null. */\n async reminder(id: string): Promise<ExpoCalendarReminder | null> {\n return this.ios() ? this.native!.ExpoCalendarReminder.get(id) : null;\n }\n\n /** The accounts the calendars belong to, on iOS: iCloud, Exchange, a subscription. */\n sources(): Source[] {\n return this.ios() ? this.native!.getSourcesSync() : [];\n }\n\n private calendarPermission(writeOnly: boolean): Permission {\n return Permission.of(\n () => this.native?.getCalendarPermissions(writeOnly) ?? Promise.resolve(UNAVAILABLE),\n () => this.native?.requestCalendarPermissions(writeOnly) ?? Promise.resolve(UNAVAILABLE),\n );\n }\n\n /** The module is here and the app is on iOS, where the calls it has only there exist. */\n private ios(): boolean {\n return this.native !== null && this.platform === 'ios';\n }\n}\n"]}
@@ -44,6 +44,11 @@ export interface NativeKeyboard {
44
44
  addListener(event: 'onKeyboardMove', listener: (frame: NativeKeyboardFrame) => void): {
45
45
  remove(): void;
46
46
  };
47
+ /**
48
+ * How far below the top of the screen the app's window starts, in points. A build made before
49
+ * the module had it has no such method.
50
+ */
51
+ windowTopOnScreen?(): number;
47
52
  }
48
53
  /**
49
54
  * The keyboard as the native module reports it, as it starts to move and at every frame of the
package/dist/keyboard.js CHANGED
@@ -92,6 +92,9 @@ export function nativeKeyboardSource(native, fallback = keyboardSource()) {
92
92
  get windowTop() {
93
93
  return fallback.windowTop;
94
94
  },
95
+ get screenTop() {
96
+ return native.windowTopOnScreen?.() ?? 0;
97
+ },
95
98
  };
96
99
  }
97
100
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"keyboard.js","sourceRoot":"","sources":["../src/keyboard.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `provideNativeKeyboard()`: the keyboard's motion on Android, from this package's native half.\n *\n * React Native on Android reports the keyboard once the window's insets have changed, as it starts\n * to move, with no duration: a `<keyboard-avoiding-view>` jumps to where the keyboard is going and a\n * `<keyboard-dock>` jumps onto it, while the keyboard slides up underneath. iOS reports the motion\n * as it starts, with its duration and curve, and the same layouts move with the keyboard there.\n *\n * With this, Android does too. The `Keyboard` service hears of the motion as it starts, with\n * Android's duration, and its `position` follows every frame of it, which a\n * `<keyboard-avoiding-view>` moves with, since Android animates no layout alongside the keyboard by\n * default; and a `<keyboard-dock>` follows it frame by frame on the native side, as one does on iOS\n * with react-native-keyboard-controller. Off\n * Android, and in a build without this package's native half, such as Expo Go, it provides nothing\n * and React Native's own events are what there is.\n *\n * ```ts\n * bootstrap(App, { providers: [provideNativeKeyboard()] });\n * ```\n */\nimport { type Provider } from '@angular/core';\nimport {\n KEYBOARD_MOTION,\n Keyboard,\n keyboardSource,\n type KeyboardMetrics,\n type KeyboardSource,\n} from '@ng-native/device';\nimport { currentPlatform } from './native.ts';\nimport { expoViewName } from './register-expo-view.ts';\n\nconst MODULE = 'NgNativeKeyboard';\n\n/** What the native module sends as the keyboard starts to move. */\nexport interface NativeKeyboardChange {\n /** Points above the system bars; zero for a keyboard going away. */\n readonly height: number;\n /** The keyboard's top edge on the screen, in points. Absent for a keyboard going away. */\n readonly screenY?: number;\n readonly duration: number;\n readonly easing: string;\n}\n\n/** Where the keyboard is at one frame of its motion, or that the motion is over. */\nexport type NativeKeyboardFrame =\n { readonly height: number; readonly screenY?: number } | { readonly end: true };\n\n/** This package's native keyboard module. A test provides a stand-in. */\nexport interface NativeKeyboard {\n addListener(\n event: 'onKeyboardChange',\n listener: (change: NativeKeyboardChange) => void,\n ): { remove(): void };\n addListener(\n event: 'onKeyboardMove',\n listener: (frame: NativeKeyboardFrame) => void,\n ): { remove(): void };\n}\n\n/** How long React Native's own event waits for the native one that says the same, in ms. */\nconst OVERTAKEN_MS = 100;\n\n/** Heights closer than this, in points, are one: the two report it through different roundings. */\nconst SAME_HEIGHT = 0.5;\n\n/** The module where the build has it, on Android. */\nfunction nativeKeyboard(): NativeKeyboard | null {\n if (currentPlatform() !== 'android') return null;\n return (\n (globalThis as { expo?: { modules?: Record<string, NativeKeyboard | undefined> } }).expo\n ?.modules?.[MODULE] ?? null\n );\n}\n\n/** A native height or edge as the metrics carry it: only the fields that are there. */\nconst metricsOf = (at: {\n readonly height: number;\n readonly screenY?: number;\n}): KeyboardMetrics => ({\n height: at.height,\n ...(at.screenY !== undefined && { screenY: at.screenY }),\n});\n\n/**\n * The keyboard as the native module reports it, as it starts to move and at every frame of the\n * motion, and as React Native's own events report it: they still come, and they are what a window\n * of its own, a modal's, has. They arrive at about the moment the native one does, sometimes just\n * before it, so one waits a moment and is dropped when the native one says the same; reported\n * first, it would hand a layout following the frames the destination before the motion began.\n */\nexport function nativeKeyboardSource(\n native: NativeKeyboard,\n fallback: KeyboardSource = keyboardSource(),\n): KeyboardSource {\n return {\n subscribe: (listener) => {\n let last: number | null = null;\n let waiting: ReturnType<typeof setTimeout> | undefined;\n const report = (metrics: KeyboardMetrics) => {\n last = metrics.height;\n listener(metrics);\n };\n const subscription = native.addListener('onKeyboardChange', (change) => {\n clearTimeout(waiting);\n report({ ...metricsOf(change), duration: change.duration, easing: change.easing });\n });\n // A motion watching began part way through sends its frames and end but not its change,\n // which went before: where its last frame left the keyboard is reported at the end, as a\n // jump, unless something already said so.\n let reached: KeyboardMetrics | null = null;\n const frames = native.addListener('onKeyboardMove', (frame) => {\n if (!('end' in frame)) reached = metricsOf(frame);\n else if (reached && (last === null || Math.abs(reached.height - last) >= SAME_HEIGHT))\n report({ ...reached, duration: 0 });\n });\n const stop = fallback.subscribe((metrics) => {\n clearTimeout(waiting);\n waiting = setTimeout(() => {\n if (last === null || Math.abs(metrics.height - last) >= SAME_HEIGHT) report(metrics);\n }, OVERTAKEN_MS);\n });\n return () => {\n clearTimeout(waiting);\n subscription.remove();\n frames.remove();\n stop();\n };\n },\n subscribeMotion: (listener) => {\n const subscription = native.addListener('onKeyboardMove', (frame) =>\n listener('end' in frame ? null : metricsOf(frame)),\n );\n return () => subscription.remove();\n },\n dismiss: () => fallback.dismiss(),\n // The module's `screenY` is from the top of the screen as React Native's is.\n get windowTop() {\n return fallback.windowTop;\n },\n };\n}\n\n/**\n * Follow the keyboard on Android as it moves rather than once it has: see this file. Nothing to\n * install beyond this package; a build made before it had this native module, and Expo Go, keep\n * React Native's own events.\n */\nexport function provideNativeKeyboard(): Provider[] {\n return [\n {\n provide: Keyboard.SOURCE,\n useFactory: () => {\n const native = nativeKeyboard();\n return native ? nativeKeyboardSource(native) : keyboardSource();\n },\n },\n {\n provide: KEYBOARD_MOTION,\n useFactory: () => (nativeKeyboard() ? { viewName: expoViewName(MODULE) } : null),\n },\n ];\n}\n"]}
1
+ {"version":3,"file":"keyboard.js","sourceRoot":"","sources":["../src/keyboard.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `provideNativeKeyboard()`: the keyboard's motion on Android, from this package's native half.\n *\n * React Native on Android reports the keyboard once the window's insets have changed, as it starts\n * to move, with no duration: a `<keyboard-avoiding-view>` jumps to where the keyboard is going and a\n * `<keyboard-dock>` jumps onto it, while the keyboard slides up underneath. iOS reports the motion\n * as it starts, with its duration and curve, and the same layouts move with the keyboard there.\n *\n * With this, Android does too. The `Keyboard` service hears of the motion as it starts, with\n * Android's duration, and its `position` follows every frame of it, which a\n * `<keyboard-avoiding-view>` moves with, since Android animates no layout alongside the keyboard by\n * default; and a `<keyboard-dock>` follows it frame by frame on the native side, as one does on iOS\n * with react-native-keyboard-controller. Off\n * Android, and in a build without this package's native half, such as Expo Go, it provides nothing\n * and React Native's own events are what there is.\n *\n * ```ts\n * bootstrap(App, { providers: [provideNativeKeyboard()] });\n * ```\n */\nimport { type Provider } from '@angular/core';\nimport {\n KEYBOARD_MOTION,\n Keyboard,\n keyboardSource,\n type KeyboardMetrics,\n type KeyboardSource,\n} from '@ng-native/device';\nimport { currentPlatform } from './native.ts';\nimport { expoViewName } from './register-expo-view.ts';\n\nconst MODULE = 'NgNativeKeyboard';\n\n/** What the native module sends as the keyboard starts to move. */\nexport interface NativeKeyboardChange {\n /** Points above the system bars; zero for a keyboard going away. */\n readonly height: number;\n /** The keyboard's top edge on the screen, in points. Absent for a keyboard going away. */\n readonly screenY?: number;\n readonly duration: number;\n readonly easing: string;\n}\n\n/** Where the keyboard is at one frame of its motion, or that the motion is over. */\nexport type NativeKeyboardFrame =\n { readonly height: number; readonly screenY?: number } | { readonly end: true };\n\n/** This package's native keyboard module. A test provides a stand-in. */\nexport interface NativeKeyboard {\n addListener(\n event: 'onKeyboardChange',\n listener: (change: NativeKeyboardChange) => void,\n ): { remove(): void };\n addListener(\n event: 'onKeyboardMove',\n listener: (frame: NativeKeyboardFrame) => void,\n ): { remove(): void };\n /**\n * How far below the top of the screen the app's window starts, in points. A build made before\n * the module had it has no such method.\n */\n windowTopOnScreen?(): number;\n}\n\n/** How long React Native's own event waits for the native one that says the same, in ms. */\nconst OVERTAKEN_MS = 100;\n\n/** Heights closer than this, in points, are one: the two report it through different roundings. */\nconst SAME_HEIGHT = 0.5;\n\n/** The module where the build has it, on Android. */\nfunction nativeKeyboard(): NativeKeyboard | null {\n if (currentPlatform() !== 'android') return null;\n return (\n (globalThis as { expo?: { modules?: Record<string, NativeKeyboard | undefined> } }).expo\n ?.modules?.[MODULE] ?? null\n );\n}\n\n/** A native height or edge as the metrics carry it: only the fields that are there. */\nconst metricsOf = (at: {\n readonly height: number;\n readonly screenY?: number;\n}): KeyboardMetrics => ({\n height: at.height,\n ...(at.screenY !== undefined && { screenY: at.screenY }),\n});\n\n/**\n * The keyboard as the native module reports it, as it starts to move and at every frame of the\n * motion, and as React Native's own events report it: they still come, and they are what a window\n * of its own, a modal's, has. They arrive at about the moment the native one does, sometimes just\n * before it, so one waits a moment and is dropped when the native one says the same; reported\n * first, it would hand a layout following the frames the destination before the motion began.\n */\nexport function nativeKeyboardSource(\n native: NativeKeyboard,\n fallback: KeyboardSource = keyboardSource(),\n): KeyboardSource {\n return {\n subscribe: (listener) => {\n let last: number | null = null;\n let waiting: ReturnType<typeof setTimeout> | undefined;\n const report = (metrics: KeyboardMetrics) => {\n last = metrics.height;\n listener(metrics);\n };\n const subscription = native.addListener('onKeyboardChange', (change) => {\n clearTimeout(waiting);\n report({ ...metricsOf(change), duration: change.duration, easing: change.easing });\n });\n // A motion watching began part way through sends its frames and end but not its change,\n // which went before: where its last frame left the keyboard is reported at the end, as a\n // jump, unless something already said so.\n let reached: KeyboardMetrics | null = null;\n const frames = native.addListener('onKeyboardMove', (frame) => {\n if (!('end' in frame)) reached = metricsOf(frame);\n else if (reached && (last === null || Math.abs(reached.height - last) >= SAME_HEIGHT))\n report({ ...reached, duration: 0 });\n });\n const stop = fallback.subscribe((metrics) => {\n clearTimeout(waiting);\n waiting = setTimeout(() => {\n if (last === null || Math.abs(metrics.height - last) >= SAME_HEIGHT) report(metrics);\n }, OVERTAKEN_MS);\n });\n return () => {\n clearTimeout(waiting);\n subscription.remove();\n frames.remove();\n stop();\n };\n },\n subscribeMotion: (listener) => {\n const subscription = native.addListener('onKeyboardMove', (frame) =>\n listener('end' in frame ? null : metricsOf(frame)),\n );\n return () => subscription.remove();\n },\n dismiss: () => fallback.dismiss(),\n // The module's `screenY` is from the top of the screen as React Native's is.\n get windowTop() {\n return fallback.windowTop;\n },\n get screenTop() {\n return native.windowTopOnScreen?.() ?? 0;\n },\n };\n}\n\n/**\n * Follow the keyboard on Android as it moves rather than once it has: see this file. Nothing to\n * install beyond this package; a build made before it had this native module, and Expo Go, keep\n * React Native's own events.\n */\nexport function provideNativeKeyboard(): Provider[] {\n return [\n {\n provide: Keyboard.SOURCE,\n useFactory: () => {\n const native = nativeKeyboard();\n return native ? nativeKeyboardSource(native) : keyboardSource();\n },\n },\n {\n provide: KEYBOARD_MOTION,\n useFactory: () => (nativeKeyboard() ? { viewName: expoViewName(MODULE) } : null),\n },\n ];\n}\n"]}
package/dist/native.js CHANGED
@@ -85,6 +85,7 @@ const NATIVE_MODULES = {
85
85
  'expo-background-task': 'ExpoBackgroundTask',
86
86
  'expo-battery': 'ExpoBattery',
87
87
  'expo-brightness': 'ExpoBrightness',
88
+ 'expo-calendar': 'CalendarNext',
88
89
  'expo-clipboard': 'ExpoClipboard',
89
90
  'expo-crypto': 'ExpoCrypto',
90
91
  'expo-device': 'ExpoDevice',
@@ -1 +1 @@
1
- {"version":3,"file":"native.js","sourceRoot":"","sources":["../src/native.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Reaching an Expo module without importing one.\n *\n * A static `import ... from 'expo-battery'` makes the file unloadable by Node, which is what used\n * to force every service into two files: the behaviour somewhere the test suite could reach, and\n * the binding somewhere it could not. A `require` inside a function has neither problem. Metro\n * still resolves the string literal at build time, so the module is bundled exactly as before and\n * an app that has not installed it still gets a build error rather than a surprise at runtime;\n * Node never evaluates the call at all, because nothing in a test asks for the real platform.\n *\n * The `catch` is doing two jobs, and only one of them is Node. In an ESM test `require` is not\n * defined, so calling it throws `ReferenceError` and the service goes inert - the same state as\n * a device that has no such sensor. On a device the throw is a module that is present but not\n * linked, which is the same answer for the same reason.\n */\n/**\n * Calls a listener the app gave. What it throws, or rejects with when it is asynchronous, goes to\n * `report`, so one failing listener does not stop what calls it.\n */\nexport function isolated(call: () => unknown, report: (failure: unknown) => void): void {\n try {\n const done = call();\n if (done instanceof Promise) done.catch(report);\n } catch (failure) {\n report(failure);\n }\n}\n\nexport function optional<T>(load: () => T): T | null {\n try {\n return load();\n } catch {\n return null;\n }\n}\n\n/** The platforms an Expo module is written for. */\nexport type ModulePlatform = 'ios' | 'android' | 'web';\n\n/**\n * A module the app needs and does not have: the package is not installed, or it is and the app was\n * not rebuilt since, so its native half is not in the binary. Development builds and Expo Go carry\n * only the native modules they were built with.\n */\nexport class MissingModuleError extends Error {\n override readonly name = 'MissingModuleError';\n /** The package, as it is installed: `expo-haptics`. */\n readonly module: string;\n\n constructor(module: string, platform: ModulePlatform, cause?: unknown, message?: string) {\n super(\n message ??\n (platform === 'web'\n ? `${module} is not installed. Install it with \"npx expo install ${module}\", then restart the dev server.`\n : `${module} is not in this build of the app. Install it with \"npx expo install ${module}\", ` +\n `then rebuild the app (\"npx expo run:${platform}\", or a new EAS build): a development ` +\n `build, and Expo Go, contain only the native modules they were built with.`),\n { cause },\n );\n this.module = module;\n }\n}\n\n/**\n * The `MissingModuleError` to throw where `expoModule` answered null: the module is installed or not, but there is\n * nothing to load it on. In Node, where a test runs, that is every native module, and \"install it\"\n * would be advice to do what is already done; `inTest` says what a test does instead. On a platform\n * the module does not support, it says that.\n */\nexport function unavailable(module: string, inTest: string): MissingModuleError {\n const platform = currentPlatform();\n const message =\n platform === null\n ? `[angular-native] ${module} has no native module to load in Node, where a test runs. ${inTest}`\n : `[angular-native] ${module} is not available on ${platform}.`;\n // The platform is only read for the default message, which this replaces.\n return new MissingModuleError(module, platform ?? 'web', undefined, message);\n}\n\n/** The platform the app is running on, or null in Node, where there is none to ask. */\nexport function currentPlatform(): ModulePlatform | null {\n return optional(\n () => (require('react-native') as { Platform: { OS: string } }).Platform.OS as ModulePlatform,\n );\n}\n\n/**\n * For each Expo package whose JavaScript requires a native module as it is evaluated, and so\n * throws when its native half is not in the build, one of those native modules. Any one of them\n * says whether the package's native half is there, and each of these is registered on both iOS and\n * Android.\n */\nconst NATIVE_MODULES: Readonly<Record<string, string>> = {\n 'expo-application': 'ExpoApplication',\n 'expo-asset': 'ExpoAsset',\n 'expo-audio': 'ExpoAudio',\n 'expo-background-task': 'ExpoBackgroundTask',\n 'expo-battery': 'ExpoBattery',\n 'expo-brightness': 'ExpoBrightness',\n 'expo-clipboard': 'ExpoClipboard',\n 'expo-crypto': 'ExpoCrypto',\n 'expo-device': 'ExpoDevice',\n 'expo-document-picker': 'ExpoDocumentPicker',\n 'expo-file-system': 'FileSystem',\n 'expo-foldables': 'ExpoFoldables',\n 'expo-font': 'ExpoFontLoader',\n 'expo-image-manipulator': 'ExpoImageManipulator',\n 'expo-image-picker': 'ExponentImagePicker',\n 'expo-keep-awake': 'ExpoKeepAwake',\n 'expo-local-authentication': 'ExpoLocalAuthentication',\n 'expo-local-llm': 'ExpoLocalLlm',\n 'expo-localization': 'ExpoLocalization',\n 'expo-location': 'ExpoLocation',\n 'expo-media-library': 'ExpoMediaLibrary',\n 'expo-network': 'ExpoNetwork',\n 'expo-notifications': 'ExpoNotificationPresenter',\n 'expo-screen-capture': 'ExpoScreenCapture',\n 'expo-screen-orientation': 'ExpoScreenOrientation',\n 'expo-secure-store': 'ExpoSecureStore',\n 'expo-sensors': 'ExponentAccelerometer',\n 'expo-sqlite': 'ExpoSQLite',\n 'expo-store-review': 'ExpoStoreReview',\n 'expo-tracking-transparency': 'ExpoTrackingTransparency',\n 'expo-updates': 'ExpoUpdates',\n 'expo-video': 'ExpoVideo',\n 'expo-web-browser': 'ExpoWebBrowser',\n};\n\n/**\n * Whether `module`'s native half is missing from the build on `platform`, asked of Expo before its\n * JavaScript is evaluated. That JavaScript throws while it is being evaluated when its native module\n * is not there, and Metro reports that as fatal, before any `catch` here, whenever it is not inside\n * another module's load: in a service's factory, say. Not on the web, where a package registers its\n * module only once it is evaluated.\n */\nfunction nativeHalfMissing(module: string, platform: ModulePlatform | null): boolean {\n const name = NATIVE_MODULES[module];\n if (!name || platform === null || platform === 'web') return false;\n const core = optional(() => require('expo-modules-core') as typeof import('expo-modules-core'));\n return core !== null && !core.requireOptionalNativeModule(name);\n}\n\n/**\n * The Expo module a service needs.\n *\n * Where the module exists for the platform the app is on, a module that is missing is a mistake\n * the developer can fix, so using what this answers throws a `MissingModuleError` that says how -\n * rather than leave a feature that silently does nothing. Using it, not asking for it: see\n * `missing`. Anywhere it cannot exist - an iOS-only module on Android, the\n * web, and Node, where a test runs with no platform at all - this answers null, and the service\n * goes inert, as code shared across platforms needs it to.\n *\n * `load` answering null or undefined counts as missing too: `requireOptionalNativeModule` answers\n * null rather than throwing. So does a package whose native half is not in the build, which `load`\n * is not called for: see `nativeHalfMissing`.\n */\nexport function expoModule<T>(\n module: string,\n load: () => T | null | undefined,\n platforms: readonly ModulePlatform[] = ['ios', 'android'],\n): T | null {\n const platform = currentPlatform();\n let failure: unknown;\n try {\n const loaded = nativeHalfMissing(module, platform) ? null : load();\n if (loaded != null) return loaded;\n } catch (error) {\n failure = error;\n }\n if (platform === null || !platforms.includes(platform)) return null;\n return missing(new MissingModuleError(module, platform, failure));\n}\n\n/** What Angular asks of any injected value, and `await` of any value: never the module's. */\nconst ASKED_OF_ANY = new Set(['then', 'ngOnDestroy', 'name']);\n\n/**\n * A module that is not there, which throws `error` when it is used rather than when it is asked\n * for. Thrown from a token's factory or a service's constructor, the error would be the one the\n * first injection sees: Angular leaves the token marked as being made, and every injection after\n * it fails with NG0200, \"Circular dependency\", which names nothing to install.\n *\n * Not thenable, and quiet to a symbol, so awaiting it or logging it does not throw, nor Angular\n * asking an injected value whether it has an `ngOnDestroy` or is its own not-found marker, by\n * `name`.\n */\nfunction missing<T>(error: MissingModuleError): T {\n const fail = (): never => {\n throw error;\n };\n // A function, so calling it, or a member read off it, is a use that says so too.\n const standIn = new Proxy(function standIn() {}, {\n get: (_, key) => (typeof key === 'symbol' || ASKED_OF_ANY.has(key) ? undefined : fail()),\n set: fail,\n has: fail,\n apply: fail,\n construct: fail,\n ownKeys: fail,\n deleteProperty: fail,\n defineProperty: fail,\n getOwnPropertyDescriptor: fail,\n });\n missingErrors.set(standIn, error);\n return standIn as T;\n}\n\n/** The error each stand-in for a missing module throws when it is used. */\nconst missingErrors = new WeakMap<object, MissingModuleError>();\n\n/** Whether `value` is the stand-in for a module missing from the build. */\nconst isMissing = (value: unknown): boolean =>\n typeof value === 'function' && missingErrors.has(value);\n\n/**\n * The module, or null where it is missing from the build: for what a service does as it is made,\n * a listener or a first read, which is skipped then rather than thrown, so the service is made and\n * what the app calls on it is what says the module is missing. See `missing`. A factory that\n * builds over the module hands the stand-in on where it is missing (`if (!present(expo)) return\n * expo as never`), for the same reason.\n */\nexport function present<T>(value: T | null | undefined): T | null {\n return value == null || isMissing(value) ? null : value;\n}\n\n/**\n * As `expoModule`, throwing at once where the module is missing: for a function an app calls\n * itself, a player, a database or the splash screen, where no token is left marked and a failure\n * after the call would be caught and lost.\n */\nexport function expoModuleNow<T>(\n module: string,\n load: () => T | null | undefined,\n platforms?: readonly ModulePlatform[],\n): T | null {\n const found = expoModule(module, load, platforms);\n const error = found && missingErrors.get(found as object);\n if (error) throw error;\n return found;\n}\n"]}
1
+ {"version":3,"file":"native.js","sourceRoot":"","sources":["../src/native.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Reaching an Expo module without importing one.\n *\n * A static `import ... from 'expo-battery'` makes the file unloadable by Node, which is what used\n * to force every service into two files: the behaviour somewhere the test suite could reach, and\n * the binding somewhere it could not. A `require` inside a function has neither problem. Metro\n * still resolves the string literal at build time, so the module is bundled exactly as before and\n * an app that has not installed it still gets a build error rather than a surprise at runtime;\n * Node never evaluates the call at all, because nothing in a test asks for the real platform.\n *\n * The `catch` is doing two jobs, and only one of them is Node. In an ESM test `require` is not\n * defined, so calling it throws `ReferenceError` and the service goes inert - the same state as\n * a device that has no such sensor. On a device the throw is a module that is present but not\n * linked, which is the same answer for the same reason.\n */\n/**\n * Calls a listener the app gave. What it throws, or rejects with when it is asynchronous, goes to\n * `report`, so one failing listener does not stop what calls it.\n */\nexport function isolated(call: () => unknown, report: (failure: unknown) => void): void {\n try {\n const done = call();\n if (done instanceof Promise) done.catch(report);\n } catch (failure) {\n report(failure);\n }\n}\n\nexport function optional<T>(load: () => T): T | null {\n try {\n return load();\n } catch {\n return null;\n }\n}\n\n/** The platforms an Expo module is written for. */\nexport type ModulePlatform = 'ios' | 'android' | 'web';\n\n/**\n * A module the app needs and does not have: the package is not installed, or it is and the app was\n * not rebuilt since, so its native half is not in the binary. Development builds and Expo Go carry\n * only the native modules they were built with.\n */\nexport class MissingModuleError extends Error {\n override readonly name = 'MissingModuleError';\n /** The package, as it is installed: `expo-haptics`. */\n readonly module: string;\n\n constructor(module: string, platform: ModulePlatform, cause?: unknown, message?: string) {\n super(\n message ??\n (platform === 'web'\n ? `${module} is not installed. Install it with \"npx expo install ${module}\", then restart the dev server.`\n : `${module} is not in this build of the app. Install it with \"npx expo install ${module}\", ` +\n `then rebuild the app (\"npx expo run:${platform}\", or a new EAS build): a development ` +\n `build, and Expo Go, contain only the native modules they were built with.`),\n { cause },\n );\n this.module = module;\n }\n}\n\n/**\n * The `MissingModuleError` to throw where `expoModule` answered null: the module is installed or not, but there is\n * nothing to load it on. In Node, where a test runs, that is every native module, and \"install it\"\n * would be advice to do what is already done; `inTest` says what a test does instead. On a platform\n * the module does not support, it says that.\n */\nexport function unavailable(module: string, inTest: string): MissingModuleError {\n const platform = currentPlatform();\n const message =\n platform === null\n ? `[angular-native] ${module} has no native module to load in Node, where a test runs. ${inTest}`\n : `[angular-native] ${module} is not available on ${platform}.`;\n // The platform is only read for the default message, which this replaces.\n return new MissingModuleError(module, platform ?? 'web', undefined, message);\n}\n\n/** The platform the app is running on, or null in Node, where there is none to ask. */\nexport function currentPlatform(): ModulePlatform | null {\n return optional(\n () => (require('react-native') as { Platform: { OS: string } }).Platform.OS as ModulePlatform,\n );\n}\n\n/**\n * For each Expo package whose JavaScript requires a native module as it is evaluated, and so\n * throws when its native half is not in the build, one of those native modules. Any one of them\n * says whether the package's native half is there, and each of these is registered on both iOS and\n * Android.\n */\nconst NATIVE_MODULES: Readonly<Record<string, string>> = {\n 'expo-application': 'ExpoApplication',\n 'expo-asset': 'ExpoAsset',\n 'expo-audio': 'ExpoAudio',\n 'expo-background-task': 'ExpoBackgroundTask',\n 'expo-battery': 'ExpoBattery',\n 'expo-brightness': 'ExpoBrightness',\n 'expo-calendar': 'CalendarNext',\n 'expo-clipboard': 'ExpoClipboard',\n 'expo-crypto': 'ExpoCrypto',\n 'expo-device': 'ExpoDevice',\n 'expo-document-picker': 'ExpoDocumentPicker',\n 'expo-file-system': 'FileSystem',\n 'expo-foldables': 'ExpoFoldables',\n 'expo-font': 'ExpoFontLoader',\n 'expo-image-manipulator': 'ExpoImageManipulator',\n 'expo-image-picker': 'ExponentImagePicker',\n 'expo-keep-awake': 'ExpoKeepAwake',\n 'expo-local-authentication': 'ExpoLocalAuthentication',\n 'expo-local-llm': 'ExpoLocalLlm',\n 'expo-localization': 'ExpoLocalization',\n 'expo-location': 'ExpoLocation',\n 'expo-media-library': 'ExpoMediaLibrary',\n 'expo-network': 'ExpoNetwork',\n 'expo-notifications': 'ExpoNotificationPresenter',\n 'expo-screen-capture': 'ExpoScreenCapture',\n 'expo-screen-orientation': 'ExpoScreenOrientation',\n 'expo-secure-store': 'ExpoSecureStore',\n 'expo-sensors': 'ExponentAccelerometer',\n 'expo-sqlite': 'ExpoSQLite',\n 'expo-store-review': 'ExpoStoreReview',\n 'expo-tracking-transparency': 'ExpoTrackingTransparency',\n 'expo-updates': 'ExpoUpdates',\n 'expo-video': 'ExpoVideo',\n 'expo-web-browser': 'ExpoWebBrowser',\n};\n\n/**\n * Whether `module`'s native half is missing from the build on `platform`, asked of Expo before its\n * JavaScript is evaluated. That JavaScript throws while it is being evaluated when its native module\n * is not there, and Metro reports that as fatal, before any `catch` here, whenever it is not inside\n * another module's load: in a service's factory, say. Not on the web, where a package registers its\n * module only once it is evaluated.\n */\nfunction nativeHalfMissing(module: string, platform: ModulePlatform | null): boolean {\n const name = NATIVE_MODULES[module];\n if (!name || platform === null || platform === 'web') return false;\n const core = optional(() => require('expo-modules-core') as typeof import('expo-modules-core'));\n return core !== null && !core.requireOptionalNativeModule(name);\n}\n\n/**\n * The Expo module a service needs.\n *\n * Where the module exists for the platform the app is on, a module that is missing is a mistake\n * the developer can fix, so using what this answers throws a `MissingModuleError` that says how -\n * rather than leave a feature that silently does nothing. Using it, not asking for it: see\n * `missing`. Anywhere it cannot exist - an iOS-only module on Android, the\n * web, and Node, where a test runs with no platform at all - this answers null, and the service\n * goes inert, as code shared across platforms needs it to.\n *\n * `load` answering null or undefined counts as missing too: `requireOptionalNativeModule` answers\n * null rather than throwing. So does a package whose native half is not in the build, which `load`\n * is not called for: see `nativeHalfMissing`.\n */\nexport function expoModule<T>(\n module: string,\n load: () => T | null | undefined,\n platforms: readonly ModulePlatform[] = ['ios', 'android'],\n): T | null {\n const platform = currentPlatform();\n let failure: unknown;\n try {\n const loaded = nativeHalfMissing(module, platform) ? null : load();\n if (loaded != null) return loaded;\n } catch (error) {\n failure = error;\n }\n if (platform === null || !platforms.includes(platform)) return null;\n return missing(new MissingModuleError(module, platform, failure));\n}\n\n/** What Angular asks of any injected value, and `await` of any value: never the module's. */\nconst ASKED_OF_ANY = new Set(['then', 'ngOnDestroy', 'name']);\n\n/**\n * A module that is not there, which throws `error` when it is used rather than when it is asked\n * for. Thrown from a token's factory or a service's constructor, the error would be the one the\n * first injection sees: Angular leaves the token marked as being made, and every injection after\n * it fails with NG0200, \"Circular dependency\", which names nothing to install.\n *\n * Not thenable, and quiet to a symbol, so awaiting it or logging it does not throw, nor Angular\n * asking an injected value whether it has an `ngOnDestroy` or is its own not-found marker, by\n * `name`.\n */\nfunction missing<T>(error: MissingModuleError): T {\n const fail = (): never => {\n throw error;\n };\n // A function, so calling it, or a member read off it, is a use that says so too.\n const standIn = new Proxy(function standIn() {}, {\n get: (_, key) => (typeof key === 'symbol' || ASKED_OF_ANY.has(key) ? undefined : fail()),\n set: fail,\n has: fail,\n apply: fail,\n construct: fail,\n ownKeys: fail,\n deleteProperty: fail,\n defineProperty: fail,\n getOwnPropertyDescriptor: fail,\n });\n missingErrors.set(standIn, error);\n return standIn as T;\n}\n\n/** The error each stand-in for a missing module throws when it is used. */\nconst missingErrors = new WeakMap<object, MissingModuleError>();\n\n/** Whether `value` is the stand-in for a module missing from the build. */\nconst isMissing = (value: unknown): boolean =>\n typeof value === 'function' && missingErrors.has(value);\n\n/**\n * The module, or null where it is missing from the build: for what a service does as it is made,\n * a listener or a first read, which is skipped then rather than thrown, so the service is made and\n * what the app calls on it is what says the module is missing. See `missing`. A factory that\n * builds over the module hands the stand-in on where it is missing (`if (!present(expo)) return\n * expo as never`), for the same reason.\n */\nexport function present<T>(value: T | null | undefined): T | null {\n return value == null || isMissing(value) ? null : value;\n}\n\n/**\n * As `expoModule`, throwing at once where the module is missing: for a function an app calls\n * itself, a player, a database or the splash screen, where no token is left marked and a failure\n * after the call would be caught and lost.\n */\nexport function expoModuleNow<T>(\n module: string,\n load: () => T | null | undefined,\n platforms?: readonly ModulePlatform[],\n): T | null {\n const found = expoModule(module, load, platforms);\n const error = found && missingErrors.get(found as object);\n if (error) throw error;\n return found;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ng-native/expo",
3
- "version": "0.18.0",
3
+ "version": "0.18.2",
4
4
  "description": "Expo modules as Angular services for Angular Native, plus registerExpoView for a module's native view.",
5
5
  "keywords": [
6
6
  "angular",
@@ -63,6 +63,10 @@
63
63
  "types": "./dist/browser.d.ts",
64
64
  "default": "./dist/browser.js"
65
65
  },
66
+ "./calendar": {
67
+ "types": "./dist/calendar.d.ts",
68
+ "default": "./dist/calendar.js"
69
+ },
66
70
  "./camera": {
67
71
  "types": "./dist/camera.d.ts",
68
72
  "default": "./dist/camera.js"
@@ -221,8 +225,8 @@
221
225
  "access": "public"
222
226
  },
223
227
  "dependencies": {
224
- "@ng-native/device": "0.18.0",
225
- "@ng-native/fabric": "0.18.0"
228
+ "@ng-native/device": "0.18.2",
229
+ "@ng-native/fabric": "0.18.2"
226
230
  },
227
231
  "nx": {
228
232
  "tags": [
@@ -247,6 +251,7 @@
247
251
  "expo-background-task": "^57.0.0 || ^58.0.0",
248
252
  "expo-battery": "^57.0.0 || ^58.0.0",
249
253
  "expo-brightness": "^57.0.0 || ^58.0.0",
254
+ "expo-calendar": "^57.0.0 || ^58.0.0",
250
255
  "expo-camera": "^57.0.0 || ^58.0.0",
251
256
  "expo-clipboard": "^57.0.0 || ^58.0.0",
252
257
  "expo-crypto": "^57.0.0 || ^58.0.0",
@@ -297,6 +302,7 @@
297
302
  "expo-background-task": "^58.0.11",
298
303
  "expo-battery": "^58.0.3",
299
304
  "expo-brightness": "^58.0.2",
305
+ "expo-calendar": "^58.0.6",
300
306
  "expo-camera": "^58.0.11",
301
307
  "expo-crypto": "^58.0.7",
302
308
  "expo-device": "^58.0.5",
@@ -356,6 +362,9 @@
356
362
  "expo-brightness": {
357
363
  "optional": true
358
364
  },
365
+ "expo-calendar": {
366
+ "optional": true
367
+ },
359
368
  "expo-camera": {
360
369
  "optional": true
361
370
  },