react-native-pointr 9.6.0 → 9.7.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.
@@ -0,0 +1,275 @@
1
+ /**
2
+ * Command pattern implementation for Pointr SDK
3
+ * Commands are immutable objects that represent actions to perform on the map
4
+ * @module commands
5
+ */
6
+
7
+ import { PTRCommandType } from '../constants';
8
+
9
+ /**
10
+ * Base class for all Pointr SDK commands
11
+ */
12
+ export abstract class PTRCommand {
13
+ readonly type: PTRCommandType;
14
+
15
+ constructor(type: PTRCommandType) {
16
+ this.type = type;
17
+ }
18
+ }
19
+
20
+ /**
21
+ * Command to show a site on the map
22
+ */
23
+ export class PTRSiteCommand extends PTRCommand {
24
+ readonly site: string;
25
+
26
+ constructor(site: string) {
27
+ super(PTRCommandType.SITE);
28
+ this.site = site;
29
+ }
30
+ }
31
+
32
+ /**
33
+ * Command to show a building on the map
34
+ */
35
+ export class PTRBuildingCommand extends PTRCommand {
36
+ readonly site: string;
37
+ readonly building: string;
38
+
39
+ constructor(site: string, building: string) {
40
+ super(PTRCommandType.BUILDING);
41
+ this.site = site;
42
+ this.building = building;
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Command to show a specific level of a building
48
+ */
49
+ export class PTRLevelCommand extends PTRCommand {
50
+ readonly site: string;
51
+ readonly building: string;
52
+ readonly level: number;
53
+
54
+ constructor(site: string, building: string, level: number) {
55
+ super(PTRCommandType.LEVEL);
56
+ this.site = site;
57
+ this.building = building;
58
+ this.level = level;
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Command to show a Point of Interest on the map
64
+ */
65
+ export class PTRPoiCommand extends PTRCommand {
66
+ readonly site: string;
67
+ readonly poi: string;
68
+
69
+ constructor(site: string, poi: string) {
70
+ super(PTRCommandType.POI);
71
+ this.site = site;
72
+ this.poi = poi;
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Command to show a navigation path to a POI from current location
78
+ */
79
+ export class PTRPathCommand extends PTRCommand {
80
+ readonly site: string;
81
+ readonly poi: string;
82
+
83
+ constructor(site: string, poi: string) {
84
+ super(PTRCommandType.PATH);
85
+ this.site = site;
86
+ this.poi = poi;
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Command to show a static path between two POIs
92
+ */
93
+ export class PTRStaticPathCommand extends PTRCommand {
94
+ readonly site: string;
95
+ readonly fromPoi: string;
96
+ readonly toPoi: string;
97
+
98
+ constructor(site: string, fromPoi: string, toPoi: string) {
99
+ super(PTRCommandType.STATIC_PATH);
100
+ this.site = site;
101
+ this.fromPoi = fromPoi;
102
+ this.toPoi = toPoi;
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Command to show static wayfinding between two POIs
108
+ */
109
+ export class PTRStaticWayfindingCommand extends PTRCommand {
110
+ readonly site: string;
111
+ readonly sourcePoi: string;
112
+ readonly destinationPoi: string;
113
+
114
+ constructor(site: string, sourcePoi: string, destinationPoi: string) {
115
+ super(PTRCommandType.STATIC_WAYFINDING);
116
+ this.site = site;
117
+ this.sourcePoi = sourcePoi;
118
+ this.destinationPoi = destinationPoi;
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Command to mark car location at a specific level
124
+ */
125
+ export class PTRMarkMyCarLevelCommand extends PTRCommand {
126
+ readonly site: string;
127
+ readonly building: string;
128
+ readonly level: number;
129
+ readonly shouldShowPopup: boolean;
130
+ readonly animationType: number;
131
+
132
+ constructor(
133
+ site: string,
134
+ building: string,
135
+ level: number,
136
+ shouldShowPopup: boolean = true,
137
+ animationType: number = 1
138
+ ) {
139
+ super(PTRCommandType.MARK_MY_CAR_LEVEL);
140
+ this.site = site;
141
+ this.building = building;
142
+ this.level = level;
143
+ this.shouldShowPopup = shouldShowPopup;
144
+ this.animationType = animationType;
145
+ }
146
+ }
147
+
148
+ /**
149
+ * Command to mark car location at a site
150
+ */
151
+ export class PTRMarkMyCarSiteCommand extends PTRCommand {
152
+ readonly site: string;
153
+ readonly shouldShowPopup: boolean;
154
+ readonly animationType: number;
155
+
156
+ constructor(
157
+ site: string,
158
+ shouldShowPopup: boolean = true,
159
+ animationType: number = 1
160
+ ) {
161
+ super(PTRCommandType.MARK_MY_CAR_SITE);
162
+ this.site = site;
163
+ this.shouldShowPopup = shouldShowPopup;
164
+ this.animationType = animationType;
165
+ }
166
+ }
167
+
168
+ /**
169
+ * Command to show marked car location at a site
170
+ */
171
+ export class PTRShowMyCarSiteCommand extends PTRCommand {
172
+ readonly site: string;
173
+ readonly shouldShowPopup: boolean;
174
+ readonly animationType: number;
175
+
176
+ constructor(
177
+ site: string,
178
+ shouldShowPopup: boolean = true,
179
+ animationType: number = 1
180
+ ) {
181
+ super(PTRCommandType.SHOW_MY_CAR_SITE);
182
+ this.site = site;
183
+ this.shouldShowPopup = shouldShowPopup;
184
+ this.animationType = animationType;
185
+ }
186
+ }
187
+
188
+ /**
189
+ * Command to start the SDK and focus on a specific location
190
+ * This is a special command that combines initialization with navigation
191
+ */
192
+ export class PTRStartAndFocusCommand {
193
+ readonly clientId: string;
194
+ readonly licenseKey: string;
195
+ readonly baseUrl: string;
196
+ readonly logLevel: number;
197
+ readonly command:
198
+ | PTRSiteCommand
199
+ | PTRBuildingCommand
200
+ | PTRLevelCommand
201
+ | PTRPoiCommand;
202
+
203
+ constructor(
204
+ clientId: string,
205
+ licenseKey: string,
206
+ baseUrl: string,
207
+ logLevel: number = 4,
208
+ command:
209
+ | PTRSiteCommand
210
+ | PTRBuildingCommand
211
+ | PTRLevelCommand
212
+ | PTRPoiCommand
213
+ ) {
214
+ this.clientId = clientId;
215
+ this.licenseKey = licenseKey;
216
+ this.baseUrl = baseUrl;
217
+ this.logLevel = logLevel;
218
+ this.command = command;
219
+ }
220
+ }
221
+
222
+ /**
223
+ * Type guard to check if a command is a PTRSiteCommand
224
+ */
225
+ export function isPTRSiteCommand(
226
+ command: PTRCommand
227
+ ): command is PTRSiteCommand {
228
+ return command.type === PTRCommandType.SITE;
229
+ }
230
+
231
+ /**
232
+ * Type guard to check if a command is a PTRBuildingCommand
233
+ */
234
+ export function isPTRBuildingCommand(
235
+ command: PTRCommand
236
+ ): command is PTRBuildingCommand {
237
+ return command.type === PTRCommandType.BUILDING;
238
+ }
239
+
240
+ /**
241
+ * Type guard to check if a command is a PTRLevelCommand
242
+ */
243
+ export function isPTRLevelCommand(
244
+ command: PTRCommand
245
+ ): command is PTRLevelCommand {
246
+ return command.type === PTRCommandType.LEVEL;
247
+ }
248
+
249
+ /**
250
+ * Type guard to check if a command is a PTRPoiCommand
251
+ */
252
+ export function isPTRPoiCommand(
253
+ command: PTRCommand
254
+ ): command is PTRPoiCommand {
255
+ return command.type === PTRCommandType.POI;
256
+ }
257
+
258
+ /**
259
+ * Type guard to check if a command is a PTRPathCommand
260
+ */
261
+ export function isPTRPathCommand(
262
+ command: PTRCommand
263
+ ): command is PTRPathCommand {
264
+ return command.type === PTRCommandType.PATH;
265
+ }
266
+
267
+ /**
268
+ * Type guard to check if a command is a PTRStaticPathCommand
269
+ */
270
+ export function isPTRStaticPathCommand(
271
+ command: PTRCommand
272
+ ): command is PTRStaticPathCommand {
273
+ return command.type === PTRCommandType.STATIC_PATH;
274
+ }
275
+
@@ -0,0 +1,130 @@
1
+ /**
2
+ * React Native component wrapper for PTRMapWidget
3
+ * @module components
4
+ */
5
+
6
+ import React, { forwardRef } from 'react';
7
+ import {
8
+ requireNativeComponent,
9
+ NativeSyntheticEvent,
10
+ ViewStyle,
11
+ } from 'react-native';
12
+ import type { PTRWayfindingEvent } from '../types/PTRWayfindingEvent';
13
+ import type { PTRMapCommandResponse } from '../types/events';
14
+ import type { PTRConfiguration, PTRMapWidgetConfiguration } from '../types/config';
15
+ import type { PTRCommand } from '../commands';
16
+
17
+ /**
18
+ * Native PTRMapWidget component
19
+ */
20
+ const NativePTRMapWidget =
21
+ requireNativeComponent<NativePTRMapWidgetProps>('PTRMapWidget');
22
+
23
+ /**
24
+ * Props for the PTRMapWidget component
25
+ */
26
+ export interface PTRMapWidgetProps {
27
+ /** Component style */
28
+ style?: ViewStyle;
29
+ /**
30
+ * Declarative command that the map widget executes automatically on mount.
31
+ * When provided the SDK is started if not already running, removing the need
32
+ * for an imperative `executeMapCommand` call after the widget loads.
33
+ *
34
+ * Supports all PTRCommand subtypes: PTRSiteCommand, PTRBuildingCommand,
35
+ * PTRLevelCommand, PTRPoiCommand, PTRPathCommand, PTRStaticPathCommand,
36
+ * PTRStaticWayfindingCommand.
37
+ *
38
+ * @example
39
+ * <PTRMapWidget command={new PTRSiteCommand('my-site')} style={{ flex: 1 }} />
40
+ */
41
+ command?: PTRCommand;
42
+ /**
43
+ * Optional SDK credentials. When provided the widget initialises the Pointr
44
+ * SDK with these credentials rather than relying on a prior `pointrSdk.initialize()` call.
45
+ */
46
+ sdkConfig?: PTRConfiguration;
47
+ /**
48
+ * Map widget UI configuration applied before the widget renders.
49
+ * Equivalent to calling `pointrSdk.setMapWidgetConfiguration(...)` imperatively.
50
+ *
51
+ * @example
52
+ * <PTRMapWidget
53
+ * mapWidgetConfig={{ isLevelSelectorEnabled: true, isJoystickEnabled: true }}
54
+ * />
55
+ */
56
+ mapWidgetConfig?: PTRMapWidgetConfiguration;
57
+ /** Callback fired when the map finishes loading */
58
+ onMapWidgetDidEndLoading?: (
59
+ event: NativeSyntheticEvent<PTRMapCommandResponse>
60
+ ) => void;
61
+ /** Callback fired when wayfinding events occur (start/end/cancel) */
62
+ onWayfindingEvent?: (
63
+ event: NativeSyntheticEvent<PTRWayfindingEvent>
64
+ ) => void;
65
+ /** Additional native props */
66
+ [key: string]: any;
67
+ }
68
+
69
+ /**
70
+ * Internal props for the native component
71
+ */
72
+ interface NativePTRMapWidgetProps extends PTRMapWidgetProps {}
73
+
74
+ /**
75
+ * PTRMapWidget - Display the Pointr indoor map
76
+ *
77
+ * This component wraps the native map widget and provides a React-friendly
78
+ * interface with proper TypeScript typing.
79
+ *
80
+ * @example
81
+ * ```tsx
82
+ * import { PTRMapWidget, PTRSiteCommand, executeMapCommand } from 'react-native-pointr';
83
+ *
84
+ * function MyMap() {
85
+ * const mapRef = useRef(null);
86
+ *
87
+ * const showSite = () => {
88
+ * executeMapCommand(mapRef, new PTRSiteCommand('my-site'));
89
+ * };
90
+ *
91
+ * return (
92
+ * <PTRMapWidget
93
+ * ref={mapRef}
94
+ * style={{ flex: 1 }}
95
+ * onMapWidgetDidEndLoading={(e) => console.log('Map loaded', e.nativeEvent)}
96
+ * onWayfindingEvent={(e) => console.log('Navigation event', e.nativeEvent)}
97
+ * />
98
+ * );
99
+ * }
100
+ * ```
101
+ */
102
+ /**
103
+ * Serialize a PTRCommand to the JSON string expected by the native command prop.
104
+ */
105
+ function serializeCommand(command: PTRCommand): string {
106
+ const base = { type: command.type, ...(command as any) };
107
+ // Remove the 'type' key duplication from spread then re-add cleanly
108
+ return JSON.stringify(base);
109
+ }
110
+
111
+ export const PTRMapWidget = forwardRef<any, PTRMapWidgetProps>(
112
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
113
+ ({ command, sdkConfig, mapWidgetConfig, ...rest }: PTRMapWidgetProps, ref: any) => {
114
+ const nativeProps: Record<string, any> = { ...rest };
115
+ if (command) {
116
+ nativeProps.command = serializeCommand(command);
117
+ }
118
+ if (sdkConfig) {
119
+ nativeProps.sdkConfig = JSON.stringify(sdkConfig);
120
+ }
121
+ if (mapWidgetConfig) {
122
+ nativeProps.mapWidgetConfig = JSON.stringify(mapWidgetConfig);
123
+ }
124
+ return <NativePTRMapWidget ref={ref} {...nativeProps} />;
125
+ }
126
+ );
127
+
128
+ PTRMapWidget.displayName = 'PTRMapWidget';
129
+
130
+ export default PTRMapWidget;
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Constants and enums for the Pointr SDK
3
+ * @module constants
4
+ */
5
+
6
+ /**
7
+ * Log levels for the Pointr SDK
8
+ */
9
+ export enum PTRLogLevel {
10
+ /** Verbose logging - all messages */
11
+ VERBOSE = 0,
12
+ /** Debug logging - debug and higher */
13
+ DEBUG = 1,
14
+ /** Info logging - informational messages and higher */
15
+ INFO = 2,
16
+ /** Warning logging - warnings and errors */
17
+ WARNING = 3,
18
+ /** Error logging - errors only */
19
+ ERROR = 4,
20
+ /** No logging */
21
+ NONE = 5,
22
+ }
23
+
24
+ /**
25
+ * SDK state values
26
+ */
27
+ export enum PTRState {
28
+ /** SDK is not initialized */
29
+ NOT_INITIALIZED = 'NOT_INITIALIZED',
30
+ /** SDK is initializing */
31
+ INITIALIZING = 'INITIALIZING',
32
+ /** SDK is initialized but not started */
33
+ INITIALIZED = 'INITIALIZED',
34
+ /** SDK is starting */
35
+ STARTING = 'STARTING',
36
+ /** SDK is running */
37
+ RUNNING = 'RUNNING',
38
+ /** SDK is stopped */
39
+ STOPPED = 'STOPPED',
40
+ /** SDK encountered an error */
41
+ ERROR = 'ERROR',
42
+ }
43
+
44
+ /**
45
+ * Animation types for map transitions
46
+ */
47
+ export enum PTRAnimationType {
48
+ /** No animation */
49
+ NONE = 'none',
50
+ /** Fade animation */
51
+ FADE = 'fade',
52
+ /** Slide animation */
53
+ SLIDE = 'slide',
54
+ /** Zoom animation */
55
+ ZOOM = 'zoom',
56
+ }
57
+
58
+ /**
59
+ * Event names emitted by the Pointr SDK
60
+ */
61
+ export const PTREvents = {
62
+ /** Fired when position is calculated */
63
+ ON_POSITION_CALCULATED: 'OnPositionManagerCalculatedLocation',
64
+ /** Fired when a building is clicked on the map */
65
+ ON_BUILDING_CLICKED: 'OnBuildingClicked',
66
+ /** Fired when a site is clicked on the map */
67
+ ON_SITE_CLICKED: 'OnSiteClicked',
68
+ /** Fired when a geofence event occurs */
69
+ ON_GEOFENCE_EVENT: 'OnGeofenceEvent',
70
+ /** Fired when wayfinding starts, ends, or is cancelled */
71
+ ON_WAYFINDING_EVENT: 'onWayfindingEvent',
72
+ /** Fired when map widget finishes loading */
73
+ ON_MAP_WIDGET_DID_END_LOADING: 'onMapWidgetDidEndLoading',
74
+ } as const;
75
+
76
+ /**
77
+ * Command types supported by the Pointr SDK
78
+ */
79
+ export enum PTRCommandType {
80
+ SITE = 'site',
81
+ BUILDING = 'building',
82
+ LEVEL = 'level',
83
+ POI = 'poi',
84
+ PATH = 'path',
85
+ STATIC_PATH = 'staticPath',
86
+ STATIC_WAYFINDING = 'staticWayfinding',
87
+ MARK_MY_CAR_LEVEL = 'markMyCarForLevel',
88
+ MARK_MY_CAR_SITE = 'markMyCarForSite',
89
+ SHOW_MY_CAR_SITE = 'showMyCarForSite',
90
+ START_AND_FOCUS = 'startAndFocus',
91
+ }
92
+
93
+ /**
94
+ * Error messages
95
+ */
96
+ export const PTRErrorMessages = {
97
+ NOT_INITIALIZED: 'Pointr SDK is not initialized. Call initialize() first.',
98
+ NOT_STARTED: 'Pointr SDK is not started. Call start() first.',
99
+ ALREADY_INITIALIZED: 'Pointr SDK is already initialized.',
100
+ INVALID_CONFIG: 'Invalid configuration provided.',
101
+ INVALID_COMMAND: 'Invalid map command provided.',
102
+ NO_MAP_REF: 'Map widget reference is required.',
103
+ NATIVE_ERROR: 'Native module error occurred.',
104
+ } as const;
@@ -0,0 +1,8 @@
1
+ export { usePointrSdk } from './usePointrSdk';
2
+ export { usePointrPosition } from './usePointrPosition';
3
+ export { usePointrPois } from './usePointrPois';
4
+ export {
5
+ usePointrGeofence,
6
+ usePointrBuildingClick,
7
+ usePointrSiteClick,
8
+ } from './usePointrEvents';
@@ -0,0 +1,40 @@
1
+ import { useEffect } from 'react';
2
+ import { pointrSdk } from '../api/PointrSdk';
3
+ import type {
4
+ PTRGeofenceEvent,
5
+ PTRBuildingClickEvent,
6
+ PTRSiteClickEvent,
7
+ } from '../types/events';
8
+
9
+ /**
10
+ * Hook to listen to geofence events.
11
+ * @param callback - Called whenever a geofence event occurs
12
+ */
13
+ export function usePointrGeofence(callback: (event: PTRGeofenceEvent) => void) {
14
+ useEffect(() => {
15
+ const subscription = pointrSdk.onGeofenceEvent(callback);
16
+ return () => subscription.remove();
17
+ }, [callback]);
18
+ }
19
+
20
+ /**
21
+ * Hook to listen to building click events.
22
+ * @param callback - Called whenever a building is tapped on the map
23
+ */
24
+ export function usePointrBuildingClick(callback: (event: PTRBuildingClickEvent) => void) {
25
+ useEffect(() => {
26
+ const subscription = pointrSdk.onBuildingClick(callback);
27
+ return () => subscription.remove();
28
+ }, [callback]);
29
+ }
30
+
31
+ /**
32
+ * Hook to listen to site click events.
33
+ * @param callback - Called whenever a site is tapped on the map
34
+ */
35
+ export function usePointrSiteClick(callback: (event: PTRSiteClickEvent) => void) {
36
+ useEffect(() => {
37
+ const subscription = pointrSdk.onSiteClick(callback);
38
+ return () => subscription.remove();
39
+ }, [callback]);
40
+ }
@@ -0,0 +1,41 @@
1
+ import { useEffect, useState, useCallback } from 'react';
2
+ import { getPois } from '../managers/PTRPoiManager';
3
+ import type { PTRPoi } from '../types/PTRPoi';
4
+
5
+ /**
6
+ * Hook to fetch and manage POIs for a site.
7
+ * @param siteId - External site identifier to fetch POIs for
8
+ * @returns POIs array, loading state, error, and a refetch function
9
+ */
10
+ export function usePointrPois(siteId?: string) {
11
+ const [pois, setPois] = useState<PTRPoi[]>([]);
12
+ const [loading, setLoading] = useState(false);
13
+ const [error, setError] = useState<Error | null>(null);
14
+
15
+ const fetchPois = useCallback(async (id: string) => {
16
+ if (!id) return;
17
+ setLoading(true);
18
+ setError(null);
19
+ try {
20
+ const fetchedPois = await getPois(id);
21
+ setPois(fetchedPois);
22
+ } catch (err) {
23
+ setError(err as Error);
24
+ } finally {
25
+ setLoading(false);
26
+ }
27
+ }, []);
28
+
29
+ useEffect(() => {
30
+ if (siteId) {
31
+ fetchPois(siteId);
32
+ }
33
+ }, [siteId, fetchPois]);
34
+
35
+ return {
36
+ pois,
37
+ loading,
38
+ error,
39
+ refetch: () => siteId && fetchPois(siteId),
40
+ };
41
+ }
@@ -0,0 +1,31 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { pointrSdk } from '../api/PointrSdk';
3
+ import type { PTRPositionEvent } from '../types/events';
4
+
5
+ /**
6
+ * Hook to listen to position updates from the Pointr SDK.
7
+ * Subscribes as soon as the component mounts; the native layer only emits
8
+ * events once the SDK is running, so the subscription is harmlessly idle
9
+ * until then.
10
+ * @param enabled - Set to false to pause listening without unmounting
11
+ * @returns Current position or null
12
+ */
13
+ export function usePointrPosition(enabled: boolean = true) {
14
+ const [position, setPosition] = useState<PTRPositionEvent | null>(null);
15
+
16
+ useEffect(() => {
17
+ if (!enabled) {
18
+ return;
19
+ }
20
+
21
+ const subscription = pointrSdk.onPositionUpdate((pos) => {
22
+ setPosition(pos);
23
+ });
24
+
25
+ return () => {
26
+ subscription.remove();
27
+ };
28
+ }, [enabled]);
29
+
30
+ return position;
31
+ }
@@ -0,0 +1,41 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { pointrSdk } from '../api/PointrSdk';
3
+ import type { PTRConfiguration } from '../types/config';
4
+ import { PTRState } from '../constants';
5
+
6
+ /**
7
+ * Hook to initialize and manage the Pointr SDK lifecycle.
8
+ * @param config - Optional configuration. When provided, initializes and starts the SDK automatically.
9
+ * @returns SDK instance with state information
10
+ */
11
+ export function usePointrSdk(config?: PTRConfiguration) {
12
+ const [state, setState] = useState<PTRState>(pointrSdk.getState());
13
+ const [isInitialized, setIsInitialized] = useState(pointrSdk.isInitialized());
14
+ const [isStarted, setIsStarted] = useState(pointrSdk.isStarted());
15
+ const [error, setError] = useState<Error | null>(null);
16
+
17
+ useEffect(() => {
18
+ if (config && !isInitialized) {
19
+ try {
20
+ pointrSdk.initialize(config);
21
+ setIsInitialized(true);
22
+ setState(pointrSdk.getState());
23
+
24
+ pointrSdk.start(() => {
25
+ setState(PTRState.RUNNING);
26
+ setIsStarted(true);
27
+ });
28
+ } catch (err) {
29
+ setError(err as Error);
30
+ }
31
+ }
32
+ }, [config, isInitialized]);
33
+
34
+ return {
35
+ sdk: pointrSdk,
36
+ state,
37
+ isInitialized,
38
+ isStarted,
39
+ error,
40
+ };
41
+ }