react-native-pointr 9.8.0 → 10.0.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 (41) hide show
  1. package/API_REFERENCE.md +284 -315
  2. package/CHANGELOG.md +42 -0
  3. package/EXTENDING.md +11 -16
  4. package/README.md +14 -14
  5. package/WAYFINDING_EVENTS.md +5 -3
  6. package/android/build.gradle +1 -1
  7. package/android/src/main/java/com/pointr/PTRCoreExtensions.kt +33 -2
  8. package/android/src/main/java/com/pointr/PTRMapWidgetActionType.kt +17 -0
  9. package/android/src/main/java/com/pointr/PTRMapWidgetManager.kt +162 -406
  10. package/android/src/main/java/com/pointr/{PointrModule.kt → PTRNativeLibrary.kt} +150 -32
  11. package/android/src/main/java/com/pointr/{PointrPackage.kt → PTRPackage.kt} +2 -2
  12. package/ios/PTRMapWidgetContainerView.swift +174 -187
  13. package/ios/PTRMapWidgetManager-Bridging.m +12 -64
  14. package/ios/PTRMapWidgetManager.swift +164 -136
  15. package/ios/PTRNativeLibrary-Bridging.m +38 -2
  16. package/ios/PTRNativeLibrary.swift +206 -26
  17. package/package.json +5 -3
  18. package/react-native-pointr.podspec +1 -1
  19. package/src/NativePointrModule.ts +70 -0
  20. package/src/PTRMapWidgetUtils.ts +67 -144
  21. package/src/actions/index.ts +171 -0
  22. package/src/api/MapWidgetApi.ts +8 -8
  23. package/src/api/PointrSdk.ts +50 -91
  24. package/src/components/index.tsx +27 -26
  25. package/src/constants/index.ts +32 -13
  26. package/src/hooks/index.ts +1 -0
  27. package/src/hooks/usePointrGeofences.ts +37 -0
  28. package/src/hooks/usePointrSdk.ts +12 -5
  29. package/src/index.tsx +37 -70
  30. package/src/managers/PTRPoiManager.ts +2 -2
  31. package/src/types/PTRPoi.ts +5 -2
  32. package/src/types/PTRPosition.ts +15 -5
  33. package/src/types/PTRSite.ts +46 -0
  34. package/src/types/PTRWayfindingEvent.ts +11 -7
  35. package/src/types/config.ts +1 -0
  36. package/src/types/events.ts +1 -0
  37. package/src/types/index.ts +4 -0
  38. package/android/src/main/java/com/pointr/PTRMapWidgetCommandType.kt +0 -20
  39. package/src/PTRCommand.ts +0 -153
  40. package/src/api/index.ts +0 -9
  41. package/src/commands/index.ts +0 -275
package/API_REFERENCE.md CHANGED
@@ -1,36 +1,28 @@
1
- # React Native Pointr - API Reference
1
+ # React Native Pointr API Reference
2
2
 
3
- > **Platform Compatibility:** This API reference is identical for both Android and iOS platforms. All methods, parameters, and behaviors are consistent across platforms.
3
+ > **Platform Compatibility:** This API reference is identical for both Android and iOS platforms unless otherwise noted.
4
4
 
5
5
  ## Table of Contents
6
6
  - [Quick Start](#quick-start)
7
7
  - [PointrSdk Class](#pointrsdk-class)
8
- - [executeMapCommand](#executemapcommand)
8
+ - [executeMapAction](#executemapaction)
9
9
  - [React Hooks](#react-hooks)
10
10
  - [PTRMapWidget Component](#ptrmapwidget-component)
11
11
  - [Constants & Enums](#constants--enums)
12
- - [Command Classes](#command-classes)
12
+ - [Action Classes](#action-classes)
13
13
  - [Types](#types)
14
14
  - [Event Listeners](#event-listeners)
15
15
  - [Complete Example](#complete-example)
16
- - [Legacy API](#legacy-api)
17
16
  - [Error Handling](#error-handling)
18
17
 
19
18
  ---
20
19
 
21
20
  ## Quick Start
22
21
 
23
- The library now exposes two API layers:
24
-
25
- | Layer | When to use |
26
- |-------|-------------|
27
- | **New API** (`PointrSdk`, `usePointrSdk`, `PTRMapWidget` declarative props) | All new integration work |
28
- | **Legacy API** (`NativeModules.PTRNativePointrLibrary`, `showMapWidget`) | Existing code — still fully supported |
29
-
30
- **Minimal declarative setup (new API):**
22
+ **Minimal declarative setup:**
31
23
 
32
24
  ```tsx
33
- import { PTRMapWidget, PTRSiteCommand } from 'react-native-pointr';
25
+ import { PTRMapWidget, PTRFocusMapAction } from 'react-native-pointr';
34
26
  import type { PTRConfiguration } from 'react-native-pointr';
35
27
 
36
28
  const SDK_CONFIG: PTRConfiguration = {
@@ -44,7 +36,7 @@ export default function MapScreen() {
44
36
  <PTRMapWidget
45
37
  style={{ flex: 1 }}
46
38
  sdkConfig={SDK_CONFIG}
47
- command={new PTRSiteCommand('<SITE_EXTERNAL_ID>')}
39
+ action={new PTRFocusMapAction('<SITE_EXTERNAL_ID>')}
48
40
  />
49
41
  );
50
42
  }
@@ -92,19 +84,18 @@ pointrSdk.initialize({
92
84
 
93
85
  ---
94
86
 
95
- #### `start(callback?)`
96
-
97
- Starts the SDK. SDK must be initialized first.
87
+ #### `start()`
98
88
 
99
- **Parameters:**
100
- - `callback` (`PTRStateCallback`, optional): Receives the native state string when the SDK is running.
89
+ Starts the SDK. Returns a `Promise<void>` that resolves when the SDK reaches the `RUNNING` state. SDK must be initialized first.
101
90
 
102
91
  **Throws:** `Error` if not initialized.
103
92
 
104
93
  ```typescript
105
- pointrSdk.start((state) => {
106
- console.log('Native state:', state); // e.g. "running"
107
- });
94
+ await pointrSdk.start();
95
+ // or with error handling:
96
+ pointrSdk.start()
97
+ .then(() => console.log('SDK running'))
98
+ .catch((err) => console.error('Start failed:', err));
108
99
  ```
109
100
 
110
101
  ---
@@ -223,7 +214,7 @@ Subscribes to `OnBuildingClicked` events.
223
214
 
224
215
  ```typescript
225
216
  const sub = pointrSdk.onBuildingClick((event) => {
226
- console.log(event.internalIdentifier, event.title);
217
+ console.log(event.buildingId, event.siteId);
227
218
  });
228
219
  ```
229
220
 
@@ -235,7 +226,7 @@ Subscribes to `OnSiteClicked` events.
235
226
 
236
227
  ```typescript
237
228
  const sub = pointrSdk.onSiteClick((event) => {
238
- console.log(event.internalIdentifier, event.title);
229
+ console.log(event.siteId, event.siteName);
239
230
  });
240
231
  ```
241
232
 
@@ -253,6 +244,19 @@ const sub = pointrSdk.onGeofenceEvent((event) => {
253
244
 
254
245
  ---
255
246
 
247
+ #### `getGeofences(siteId)`
248
+
249
+ Returns a `Promise<PTRGeofence[]>` with the geofences configured for the given site.
250
+
251
+ **Parameters:**
252
+ - `siteId` (`string`): External site identifier.
253
+
254
+ ```typescript
255
+ const geofences = await pointrSdk.getGeofences('<SITE_ID>');
256
+ ```
257
+
258
+ ---
259
+
256
260
  #### `getEventEmitter()`
257
261
 
258
262
  Returns the underlying `NativeEventEmitter` for advanced subscription use cases.
@@ -265,48 +269,48 @@ const emitter = pointrSdk.getEventEmitter();
265
269
 
266
270
  #### `getNativeModule()`
267
271
 
268
- Returns the raw `NativeModules.PTRNativePointrLibrary` reference for advanced use cases.
272
+ Returns the raw `NativeModules.PTRNativeLibrary` reference for advanced use cases not covered by the `PointrSdk` wrapper (e.g. `getPois`, `searchPois`, `isWayfindingReady`, `calculateDistance`).
269
273
 
270
274
  ```typescript
271
275
  const native = pointrSdk.getNativeModule();
272
- native.requestPermissions();
276
+ const pois = await native.getPois('<SITE_ID>');
273
277
  ```
274
278
 
275
279
  ---
276
280
 
277
- ## executeMapCommand
281
+ ## executeMapAction
278
282
 
279
283
  A convenience function that resolves `findNodeHandle` internally and dispatches a command to the native map widget.
280
284
 
281
285
  **Import:**
282
286
  ```typescript
283
- import { executeMapCommand } from 'react-native-pointr';
287
+ import { executeMapAction } from 'react-native-pointr';
284
288
  ```
285
289
 
286
290
  **Signature:**
287
291
  ```typescript
288
- function executeMapCommand(
292
+ function executeMapAction(
289
293
  mapRef: React.RefObject<any> | any,
290
- command: PTRCommand
294
+ action: PTRAction
291
295
  ): void
292
296
  ```
293
297
 
294
298
  **Parameters:**
295
299
  - `mapRef`: A React ref (or any object with a `.current` property) pointing to the rendered `PTRMapWidget`.
296
- - `command`: Any `PTRCommand` subclass instance.
300
+ - `action`: Any `PTRAction` subclass instance.
297
301
 
298
302
  **Throws:** `Error` if `mapRef` is null, the native view tag cannot be resolved, or the command is invalid.
299
303
 
300
304
  **Example:**
301
305
  ```typescript
302
306
  import { useRef } from 'react';
303
- import { PTRMapWidget, PTRPoiCommand, executeMapCommand } from 'react-native-pointr';
307
+ import { PTRMapWidget, PTRHighlightPoiAction, executeMapAction } from 'react-native-pointr';
304
308
 
305
309
  function MyMap() {
306
310
  const mapRef = useRef(null);
307
311
 
308
312
  const navigateToLobby = () => {
309
- executeMapCommand(mapRef, new PTRPoiCommand('<SITE_ID>', 'Lobby'));
313
+ executeMapAction(mapRef, new PTRHighlightPoiAction('<SITE_ID>', 'Lobby'));
310
314
  };
311
315
 
312
316
  return <PTRMapWidget ref={mapRef} style={{ flex: 1 }} />;
@@ -431,7 +435,7 @@ Subscribes to building-tap events on the map.
431
435
  import { usePointrBuildingClick } from 'react-native-pointr';
432
436
 
433
437
  usePointrBuildingClick((event) => {
434
- console.log('Building tapped:', event.internalIdentifier, event.title);
438
+ console.log('Building tapped:', event.buildingId, event.siteId);
435
439
  });
436
440
  ```
437
441
 
@@ -448,12 +452,39 @@ Subscribes to site-tap events on the map.
448
452
  import { usePointrSiteClick } from 'react-native-pointr';
449
453
 
450
454
  usePointrSiteClick((event) => {
451
- console.log('Site tapped:', event.internalIdentifier, event.title);
455
+ console.log('Site tapped:', event.siteId, event.siteName);
452
456
  });
453
457
  ```
454
458
 
455
459
  ---
456
460
 
461
+ ### `usePointrGeofences(siteId?)`
462
+
463
+ Fetches geofences for a site.
464
+
465
+ **Parameters:**
466
+ - `siteId` (string, optional): External site identifier. Fetches when this value changes.
467
+
468
+ **Returns:**
469
+ ```typescript
470
+ {
471
+ geofences: PTRGeofence[];
472
+ loading: boolean;
473
+ error: Error | null;
474
+ refresh: () => void;
475
+ }
476
+ ```
477
+
478
+ ```typescript
479
+ import { usePointrGeofences } from 'react-native-pointr';
480
+
481
+ function GeofenceList() {
482
+ const { geofences, loading } = usePointrGeofences('<SITE_ID>');
483
+ }
484
+ ```
485
+
486
+ ---
487
+
457
488
  ## PTRMapWidget Component
458
489
 
459
490
  `PTRMapWidget` is a typed React component (with `forwardRef`) that wraps the native map view.
@@ -469,7 +500,7 @@ import type { PTRMapWidgetProps } from 'react-native-pointr';
469
500
  | Prop | Type | Description |
470
501
  |------|------|-------------|
471
502
  | `style` | `ViewStyle` | Component styling |
472
- | `command` | `PTRCommand` | Declarative command executed automatically on mount |
503
+ | `action` | `PTRAction` | Declarative action executed automatically on mount |
473
504
  | `sdkConfig` | `PTRConfiguration` | When provided, initializes the SDK without a prior `pointrSdk.initialize()` call |
474
505
  | `mapWidgetConfig` | `PTRMapWidgetConfiguration` | UI configuration applied before the widget renders |
475
506
  | `onMapWidgetDidEndLoading` | `(event: NativeSyntheticEvent<PTRMapCommandResponse>) => void` | Fired when the map finishes loading a command |
@@ -477,10 +508,10 @@ import type { PTRMapWidgetProps } from 'react-native-pointr';
477
508
 
478
509
  ### Declarative usage (recommended)
479
510
 
480
- Pass `command`, `sdkConfig`, and `mapWidgetConfig` as props so the widget handles initialization automatically:
511
+ Pass `action`, `sdkConfig`, and `mapWidgetConfig` as props so the widget handles initialization automatically:
481
512
 
482
513
  ```tsx
483
- import { PTRMapWidget, PTRSiteCommand } from 'react-native-pointr';
514
+ import { PTRMapWidget, PTRFocusMapAction } from 'react-native-pointr';
484
515
  import type { PTRConfiguration, PTRMapWidgetConfiguration } from 'react-native-pointr';
485
516
 
486
517
  const SDK_CONFIG: PTRConfiguration = {
@@ -501,7 +532,7 @@ function MapScreen() {
501
532
  style={{ flex: 1 }}
502
533
  sdkConfig={SDK_CONFIG}
503
534
  mapWidgetConfig={MAP_CONFIG}
504
- command={new PTRSiteCommand('<SITE_ID>')}
535
+ action={new PTRFocusMapAction('<SITE_ID>')}
505
536
  onMapWidgetDidEndLoading={(e) => console.log('Loaded', e.nativeEvent)}
506
537
  onWayfindingEvent={(e) => console.log('Navigation', e.nativeEvent)}
507
538
  />
@@ -511,17 +542,17 @@ function MapScreen() {
511
542
 
512
543
  ### Imperative usage
513
544
 
514
- Use `ref` + `executeMapCommand` to dispatch commands after mount:
545
+ Use `ref` + `executeMapAction` to dispatch actions after mount:
515
546
 
516
547
  ```tsx
517
548
  import { useRef } from 'react';
518
- import { PTRMapWidget, PTRPoiCommand, executeMapCommand } from 'react-native-pointr';
549
+ import { PTRMapWidget, PTRHighlightPoiAction, executeMapAction } from 'react-native-pointr';
519
550
 
520
551
  function MapScreen() {
521
552
  const mapRef = useRef(null);
522
553
 
523
554
  const goToLobby = () => {
524
- executeMapCommand(mapRef, new PTRPoiCommand('<SITE_ID>', 'Lobby'));
555
+ executeMapAction(mapRef, new PTRHighlightPoiAction('<SITE_ID>', 'Lobby'));
525
556
  };
526
557
 
527
558
  return (
@@ -576,21 +607,18 @@ enum PTRState {
576
607
 
577
608
  ---
578
609
 
579
- ### `PTRCommandType`
580
-
581
- ```typescript
582
- enum PTRCommandType {
583
- SITE = 'site',
584
- BUILDING = 'building',
585
- LEVEL = 'level',
586
- POI = 'poi',
587
- PATH = 'path',
588
- STATIC_PATH = 'staticPath',
589
- STATIC_WAYFINDING = 'staticWayfinding',
590
- MARK_MY_CAR_LEVEL = 'markMyCarForLevel',
591
- MARK_MY_CAR_SITE = 'markMyCarForSite',
592
- SHOW_MY_CAR_SITE = 'showMyCarForSite',
593
- START_AND_FOCUS = 'startAndFocus',
610
+ ### `PTRActionType`
611
+
612
+ ```typescript
613
+ enum PTRActionType {
614
+ FOCUS_MAP = 'focusMap',
615
+ HIGHLIGHT_POI = 'highlightPoi',
616
+ DISPLAY_ROUTE = 'displayRoute',
617
+ START_WAYFINDING = 'startWayfinding',
618
+ MARK_MY_CAR = 'markMyCar',
619
+ SHOW_MY_CAR = 'showMyCar',
620
+ FOCUS_COORDINATE = 'focusCoordinate',
621
+ HIGHLIGHT_CATEGORY = 'highlightCategory',
594
622
  }
595
623
  ```
596
624
 
@@ -598,7 +626,7 @@ enum PTRCommandType {
598
626
 
599
627
  ### `PTRAnimationType`
600
628
 
601
- Animation type constants for map transitions.
629
+ Animation type constants for map transitions. Used in `PTRMarkMyCarAction` and `PTRShowMyCarAction`.
602
630
 
603
631
  ```typescript
604
632
  enum PTRAnimationType {
@@ -609,7 +637,64 @@ enum PTRAnimationType {
609
637
  }
610
638
  ```
611
639
 
612
- > **Note:** The "My Car" command constructors (`PTRMarkMyCarLevelCommand`, `PTRMarkMyCarSiteCommand`, `PTRShowMyCarSiteCommand`) accept `animationType` as a plain `number` parameter, not as `PTRAnimationType`. The numeric values `0`, `1`, `2` correspond to none, standard, and fly-over animation respectively.
640
+ > **Note:** `PTRMarkMyCarAction` and `PTRShowMyCarAction` accept `animationType` as a plain `number` parameter (not the enum string). Values: `0` = none, `1` = standard, `2` = fly-over.
641
+
642
+ ---
643
+
644
+ ### `PTRWayfindingMode`
645
+
646
+ Routing behaviour for turn-by-turn navigation.
647
+
648
+ ```typescript
649
+ enum PTRWayfindingMode {
650
+ NORMAL = 'normal', // Standard routing
651
+ ACCESSIBLE = 'accessible', // Avoids stairs, prefers ramps / lifts
652
+ }
653
+ ```
654
+
655
+ ---
656
+
657
+ ### `PTRMapTrackingMode`
658
+
659
+ Controls how the map follows the user's position.
660
+
661
+ ```typescript
662
+ enum PTRMapTrackingMode {
663
+ NONE = 'none',
664
+ TRACKING = 'tracking',
665
+ TRACKING_WITH_HEADING = 'trackingWithHeading',
666
+ }
667
+ ```
668
+
669
+ ---
670
+
671
+ ### `PTRMapWidgetLayoutState`
672
+
673
+ Represents the active panel state of the map widget.
674
+
675
+ ```typescript
676
+ enum PTRMapWidgetLayoutState {
677
+ IDLE = 'idle',
678
+ POI_DETAILS = 'poiDetails',
679
+ WAYFINDING = 'wayfinding',
680
+ STATIC_WAYFINDING= 'staticWayfinding',
681
+ ROUTE_SUMMARY = 'routeSummary',
682
+ }
683
+ ```
684
+
685
+ ---
686
+
687
+ ### `PTRWayfindingEventType`
688
+
689
+ Lifecycle states of a navigation session, used as `PTRWayfindingEvent.type`.
690
+
691
+ ```typescript
692
+ enum PTRWayfindingEventType {
693
+ CANCELLED = -1, // Wayfinding cancelled by the user
694
+ STARTED = 0, // Navigation session started
695
+ ENDED = 1, // Destination reached
696
+ }
697
+ ```
613
698
 
614
699
  ---
615
700
 
@@ -619,10 +704,11 @@ enum PTRAnimationType {
619
704
  enum PTRGeofenceEventType {
620
705
  ENTER = 'enter',
621
706
  EXIT = 'exit',
707
+ DWELL = 'dwell',
622
708
  }
623
709
  ```
624
710
 
625
- > **Note:** `DWELL` is not emitted by the native SDK on either platform.
711
+ > **Note:** `DWELL` is defined in the enum but is not emitted by the native SDK on either platform.
626
712
 
627
713
  ---
628
714
 
@@ -645,7 +731,7 @@ const PTREvents = {
645
731
 
646
732
  ### `PTRErrorMessages`
647
733
 
648
- Pre-defined error message strings thrown by `PointrSdk` and `executeMapCommand`.
734
+ Pre-defined error message strings thrown by `PointrSdk` and `executeMapAction`.
649
735
 
650
736
  ```typescript
651
737
  const PTRErrorMessages = {
@@ -661,173 +747,121 @@ const PTRErrorMessages = {
661
747
 
662
748
  ---
663
749
 
664
- ## Command Classes
665
-
666
- All command classes are exported from `react-native-pointr`.
667
-
668
- ### `PTRSiteCommand`
750
+ ## Action Classes
669
751
 
670
- Shows a specific site on the map.
671
-
672
- ```typescript
673
- new PTRSiteCommand(site: string)
674
- ```
675
-
676
- ```typescript
677
- new PTRSiteCommand('<SITE_EXTERNAL_ID>')
678
- ```
679
-
680
- ---
752
+ All action classes extend `PTRAction` and are exported from `react-native-pointr`. Pass an instance to `PTRMapWidget`'s `action` prop or to `executeMapAction`.
681
753
 
682
- ### `PTRBuildingCommand`
754
+ ### `PTRFocusMapAction`
683
755
 
684
- Shows a specific building within a site.
756
+ Focuses the map on a site, building, or level. Provide only as many parameters as needed for the desired zoom depth.
685
757
 
686
758
  ```typescript
687
- new PTRBuildingCommand(site: string, building: string)
759
+ new PTRFocusMapAction(site: string, building?: string, level?: number)
688
760
  ```
689
761
 
690
- ---
691
-
692
- ### `PTRLevelCommand`
693
-
694
- Shows a specific level within a building.
695
-
696
762
  ```typescript
697
- new PTRLevelCommand(site: string, building: string, level: number)
763
+ new PTRFocusMapAction('<SITE_ID>') // focus on site
764
+ new PTRFocusMapAction('<SITE_ID>', '<BUILDING_ID>') // focus on building
765
+ new PTRFocusMapAction('<SITE_ID>', '<BUILDING_ID>', 2) // focus on level 2
698
766
  ```
699
767
 
700
768
  ---
701
769
 
702
- ### `PTRPoiCommand`
770
+ ### `PTRHighlightPoiAction`
703
771
 
704
- Focuses the map on a specific POI.
772
+ Highlights a specific POI on the map.
705
773
 
706
774
  ```typescript
707
- new PTRPoiCommand(site: string, poi: string)
775
+ new PTRHighlightPoiAction(site: string, poi: string)
708
776
  ```
709
777
 
710
778
  - `poi`: POI external identifier or name.
711
779
 
712
780
  ---
713
781
 
714
- ### `PTRPathCommand`
782
+ ### `PTRDisplayRouteAction`
715
783
 
716
- Shows a navigation path from the user's current location to a POI.
784
+ Displays a static route between two POIs without requiring live user location.
717
785
 
718
786
  ```typescript
719
- new PTRPathCommand(site: string, poi: string)
787
+ new PTRDisplayRouteAction(site: string, fromPoi: string, toPoi: string)
720
788
  ```
721
789
 
722
790
  ---
723
791
 
724
- ### `PTRStaticPathCommand`
792
+ ### `PTRStartWayfindingAction`
725
793
 
726
- Shows a static path between two POIs.
794
+ Starts turn-by-turn wayfinding from the user's current position to a destination POI.
727
795
 
728
796
  ```typescript
729
- new PTRStaticPathCommand(site: string, fromPoi: string, toPoi: string)
797
+ new PTRStartWayfindingAction(site: string, poi: string)
730
798
  ```
731
799
 
732
800
  ---
733
801
 
734
- ### `PTRStaticWayfindingCommand`
802
+ ### `PTRMarkMyCarAction`
735
803
 
736
- Initiates static wayfinding between two POIs.
804
+ Marks the car location. When `building` and `level` are provided, pins to that specific level; otherwise pins at the site level using the current position.
737
805
 
738
806
  ```typescript
739
- new PTRStaticWayfindingCommand(site: string, sourcePoi: string, destinationPoi: string)
807
+ new PTRMarkMyCarAction(
808
+ site: string,
809
+ building?: string,
810
+ level?: number,
811
+ shouldShowPopup?: boolean, // default: true
812
+ animationType?: number // default: 1 (standard). 0 = none, 2 = fly-over
813
+ )
740
814
  ```
741
815
 
742
816
  ---
743
817
 
744
- ### `PTRMarkMyCarLevelCommand`
818
+ ### `PTRShowMyCarAction`
745
819
 
746
- Marks the "My Car" location at a specific level.
820
+ Shows the previously saved car location.
747
821
 
748
822
  ```typescript
749
- new PTRMarkMyCarLevelCommand(
823
+ new PTRShowMyCarAction(
750
824
  site: string,
751
- building: string,
752
- level: number,
753
- shouldShowPopup?: boolean, // default: true
754
- animationType?: number // default: 1
825
+ shouldShowPopup?: boolean, // default: true
826
+ animationType?: number // default: 1
755
827
  )
756
828
  ```
757
829
 
758
830
  ---
759
831
 
760
- ### `PTRMarkMyCarSiteCommand`
832
+ ### `PTRFocusCoordinateAction`
761
833
 
762
- Marks the "My Car" location at the current position within a site.
834
+ Focuses the map on a specific geographic coordinate, optionally at a given level.
763
835
 
764
836
  ```typescript
765
- new PTRMarkMyCarSiteCommand(
837
+ new PTRFocusCoordinateAction(
766
838
  site: string,
767
- shouldShowPopup?: boolean, // default: true
768
- animationType?: number // default: 1
839
+ latitude: number,
840
+ longitude: number,
841
+ levelIndex?: number
769
842
  )
770
843
  ```
771
844
 
772
- ---
773
-
774
- ### `PTRShowMyCarSiteCommand`
775
-
776
- Shows the previously saved "My Car" location.
777
-
778
845
  ```typescript
779
- new PTRShowMyCarSiteCommand(
780
- site: string,
781
- shouldShowPopup?: boolean, // default: true
782
- animationType?: number // default: 1
783
- )
846
+ new PTRFocusCoordinateAction('<SITE_ID>', 47.4979, 19.0402)
847
+ new PTRFocusCoordinateAction('<SITE_ID>', 47.4979, 19.0402, 2)
784
848
  ```
785
849
 
786
850
  ---
787
851
 
788
- ### `PTRStartAndFocusCommand`
852
+ ### `PTRHighlightCategoryAction` / `PTRCategoryFilterAction`
789
853
 
790
- Combines SDK initialization with a focus command in a single native dispatch. Use for deep-link or notification-driven entry points where the SDK may not yet be running.
854
+ Filters the visible POIs to only those belonging to the specified category identifiers. Pass an empty array to clear the active filter.
791
855
 
792
- > **Note:** This command is dispatched via `showMapWidget` / the legacy `UIManager` path and is not a `PTRCommand` subclass. Prefer the declarative `sdkConfig` + `command` props on `PTRMapWidget` for new code.
856
+ > Exported under both names: `PTRHighlightCategoryAction` (class name) and `PTRCategoryFilterAction` (alias).
793
857
 
794
858
  ```typescript
795
- new PTRStartAndFocusCommand(
796
- clientId: string,
797
- licenseKey: string,
798
- baseUrl: string,
799
- logLevel: number, // default: 4 (ERROR)
800
- command: PTRSiteCommand | PTRBuildingCommand | PTRLevelCommand | PTRPoiCommand
801
- )
859
+ new PTRHighlightCategoryAction(site: string, categoryIds: string[])
802
860
  ```
803
861
 
804
862
  ```typescript
805
- import { PTRStartAndFocusCommand, PTRSiteCommand, showMapWidget } from 'react-native-pointr';
806
- import { findNodeHandle } from 'react-native';
807
-
808
- const cmd = new PTRStartAndFocusCommand(
809
- '<CLIENT_ID>',
810
- '<LICENSE_KEY>',
811
- 'https://<your-instance>.pointr.cloud',
812
- 4,
813
- new PTRSiteCommand('<SITE_ID>')
814
- );
815
- showMapWidget(findNodeHandle(mapRef.current), cmd);
816
- ```
817
-
818
- ---
819
-
820
- ### Type guards
821
-
822
- ```typescript
823
- import {
824
- isPTRSiteCommand,
825
- isPTRBuildingCommand,
826
- isPTRLevelCommand,
827
- isPTRPoiCommand,
828
- isPTRPathCommand,
829
- isPTRStaticPathCommand,
830
- } from 'react-native-pointr';
863
+ new PTRHighlightCategoryAction('<SITE_ID>', ['cafes', 'restaurants'])
864
+ new PTRHighlightCategoryAction('<SITE_ID>', []) // clear filter
831
865
  ```
832
866
 
833
867
  ---
@@ -851,8 +885,6 @@ interface PTRConfiguration {
851
885
 
852
886
  ### `PTRMapWidgetConfiguration`
853
887
 
854
- Parameter names must match the boolean properties of `PTRMapWidgetConfiguration` declared in the native SDK. See [iOS SDK reference](https://pointr.blob.core.windows.net/api-ref/ios/9.6/Classes/PTRMapWidgetConfiguration.html) and [Android SDK reference](https://pointr.blob.core.windows.net/api-ref/android/9.6/-pointr%20-android%20-s-d-k%209.6.0/com.pointrlabs.ui.map.viewmodels/-p-t-r-map-widget-configuration/index.html) for the full list.
855
-
856
888
  ```typescript
857
889
  interface PTRMapWidgetConfiguration {
858
890
  readonly isLevelSelectorEnabled?: boolean;
@@ -868,6 +900,14 @@ interface PTRMapWidgetConfiguration {
868
900
  readonly shouldFocusOnFirstUserPosition?: boolean;
869
901
  readonly isQuickAccessEnabled?: boolean;
870
902
  readonly isAppBannerEnabled?: boolean;
903
+ /** Position of the exit button. Accepted values: 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' */
904
+ readonly exitButtonPosition?: string;
905
+ /** Routing mode. Defaults to PTRWayfindingMode.NORMAL. */
906
+ readonly wayfindingMode?: PTRWayfindingMode;
907
+ /** Initial map tracking mode. Defaults to PTRMapTrackingMode.NONE. */
908
+ readonly initialMapTrackingMode?: PTRMapTrackingMode;
909
+ /** Search panel layout. Accepted values: 'default' | 'minimal' */
910
+ readonly searchLayout?: string;
871
911
  }
872
912
  ```
873
913
 
@@ -877,12 +917,20 @@ interface PTRMapWidgetConfiguration {
877
917
 
878
918
  ```typescript
879
919
  interface PTRPosition {
880
- lat: number; // Latitude
881
- lon: number; // Longitude
920
+ // Short names
921
+ lat: number; // Latitude
922
+ lon: number; // Longitude
923
+ sid: string; // Site identifier
924
+ bid: string; // Building identifier
925
+ lvl: number; // Level index
882
926
  isValid: boolean;
883
- sid: string; // Site identifier
884
- bid: string; // Building identifier
885
- lvl: number; // Level index
927
+
928
+ // Readable aliases (optional — present when populated by the SDK)
929
+ latitude?: number;
930
+ longitude?: number;
931
+ siteId?: string;
932
+ buildingId?: string;
933
+ levelIndex?: number;
886
934
  }
887
935
  ```
888
936
 
@@ -890,7 +938,15 @@ interface PTRPosition {
890
938
 
891
939
  ### `PTRPositionEvent`
892
940
 
893
- The TypeScript return type of `usePointrPosition` and the argument type of `pointrSdk.onPositionUpdate` callbacks. The actual runtime payload is the raw native event object with the fields listed under [`getCurrentLocation()`](#getcurrentlocation) rather than a wrapped `PTRPosition`.
941
+ The return type of `usePointrPosition` and the callback argument of `pointrSdk.onPositionUpdate`.
942
+
943
+ ```typescript
944
+ interface PTRPositionEvent {
945
+ readonly position: PTRPosition;
946
+ readonly timestamp?: number; // milliseconds since epoch
947
+ readonly accuracy?: number; // accuracy in metres
948
+ }
949
+ ```
894
950
 
895
951
  ---
896
952
 
@@ -901,7 +957,8 @@ interface PTRPoi {
901
957
  identifier: string;
902
958
  externalIdentifier: string;
903
959
  name: string;
904
- typeCode: string;
960
+ mainType: string;
961
+ subType?: string;
905
962
  position: PTRPosition;
906
963
  geometry: PTRGeometry;
907
964
  attributes: PTRPoiAttributes;
@@ -947,20 +1004,20 @@ type PTRGeometry =
947
1004
 
948
1005
  ### `PTRWayfindingEvent`
949
1006
 
950
- Fired via `onWayfindingEvent` prop on `PTRMapWidget`.
1007
+ Fired via the `onWayfindingEvent` prop on `PTRMapWidget`.
951
1008
 
952
1009
  ```typescript
953
1010
  interface PTRWayfindingEvent {
954
- type: -1 | 0 | 1; // -1 Cancelled, 0 Started, 1 Ended
955
- poi: PTRPoi; // Destination POI
1011
+ type: PTRWayfindingEventType; // CANCELLED = -1, STARTED = 0, ENDED = 1
1012
+ poi: PTRPoi; // Destination POI
956
1013
  }
957
1014
  ```
958
1015
 
959
- | `type` value | Meaning |
960
- |-----|---------|
961
- | `-1` | Wayfinding cancelled by user |
962
- | `0` | Wayfinding started |
963
- | `1` | Wayfinding ended (completed or dismissed) |
1016
+ | `type` value | `PTRWayfindingEventType` | Meaning |
1017
+ |-------------|--------------------------|---------|
1018
+ | `-1` | `CANCELLED` | Wayfinding cancelled by user |
1019
+ | `0` | `STARTED` | Navigation session started |
1020
+ | `1` | `ENDED` | Destination reached |
964
1021
 
965
1022
  ---
966
1023
 
@@ -982,52 +1039,68 @@ interface PTRMapCommandResponse {
982
1039
 
983
1040
  ```typescript
984
1041
  interface PTRGeofenceEvent {
985
- readonly eventType: 'enter' | 'exit';
986
- readonly geofence: PTRGeofence;
1042
+ readonly eventType: PTRGeofenceEventType | string;
1043
+ readonly geofence?: PTRGeofence;
987
1044
  readonly geofenceNotification?: PTRGeofenceNotification;
988
- readonly timestamp?: number; // iOS only — milliseconds since epoch at root level
989
- readonly geofenceType?: string; // Android only — 'beacon' | 'gps' at root level
1045
+ readonly timestamp?: number; // iOS only — milliseconds since epoch
990
1046
  }
991
1047
 
992
1048
  interface PTRGeofence {
993
1049
  readonly id: string;
994
- readonly externalId: string;
1050
+ readonly externalId?: string;
995
1051
  readonly name: string;
996
- readonly geofenceType?: string; // iOS only — 'beacon' | 'gps' inside geofence object
997
- readonly position: {
998
- readonly latitude: number;
999
- readonly longitude: number;
1000
- };
1052
+ readonly geofenceType: string; // 'beacon' | 'gps'
1053
+ readonly position: PTRPosition;
1001
1054
  }
1002
1055
 
1003
1056
  interface PTRGeofenceNotification {
1004
1057
  readonly id: string;
1005
1058
  readonly message: string;
1006
- readonly timestamp: number; // milliseconds
1059
+ readonly timestamp: number; // milliseconds
1007
1060
  }
1008
1061
  ```
1009
1062
 
1010
- **Platform differences:**
1011
- - iOS: `timestamp` (milliseconds since epoch) is present at the event root level; `geofenceType` is inside the `geofence` object.
1012
- - Android: No `timestamp` at the root level; `geofenceType` is at the event root level (not inside `geofence`).
1013
-
1014
1063
  ---
1015
1064
 
1016
1065
  ### `PTRBuildingClickEvent` / `PTRSiteClickEvent`
1017
1066
 
1018
- Both events share the same payload shape emitted by the native SDK:
1019
-
1020
1067
  ```typescript
1021
1068
  interface PTRBuildingClickEvent {
1022
- readonly internalIdentifier: string;
1023
- readonly externalIdentifier: string;
1024
- readonly title: string;
1069
+ readonly siteId: string;
1070
+ readonly buildingId: string;
1071
+ readonly buildingName?: string;
1025
1072
  }
1026
1073
 
1027
1074
  interface PTRSiteClickEvent {
1028
- readonly internalIdentifier: string;
1075
+ readonly siteId: string;
1076
+ readonly siteName?: string;
1077
+ }
1078
+ ```
1079
+
1080
+ ---
1081
+
1082
+ ### `PTRSite` / `PTRBuilding` / `PTRLevel`
1083
+
1084
+ ```typescript
1085
+ interface PTRLevel {
1086
+ readonly identifier: string;
1087
+ readonly externalIdentifier: string;
1088
+ readonly name: string;
1089
+ readonly index: number; // zero-based
1090
+ }
1091
+
1092
+ interface PTRBuilding {
1093
+ readonly identifier: string;
1094
+ readonly externalIdentifier: string;
1095
+ readonly name: string;
1096
+ readonly levels: PTRLevel[];
1097
+ }
1098
+
1099
+ interface PTRSite {
1100
+ readonly identifier: string;
1029
1101
  readonly externalIdentifier: string;
1030
- readonly title: string;
1102
+ readonly name: string;
1103
+ readonly buildings: PTRBuilding[];
1031
1104
  }
1032
1105
  ```
1033
1106
 
@@ -1057,12 +1130,12 @@ usePointrGeofence((event) => {
1057
1130
 
1058
1131
  // Building click
1059
1132
  usePointrBuildingClick((event) => {
1060
- console.log('Building:', event.internalIdentifier, event.title);
1133
+ console.log('Building:', event.buildingId, event.siteId);
1061
1134
  });
1062
1135
 
1063
1136
  // Site click
1064
1137
  usePointrSiteClick((event) => {
1065
- console.log('Site:', event.internalIdentifier, event.title);
1138
+ console.log('Site:', event.siteId, event.siteName);
1066
1139
  });
1067
1140
  ```
1068
1141
 
@@ -1091,7 +1164,7 @@ Available methods: `onPositionUpdate`, `onBuildingClick`, `onSiteClick`, `onGeof
1091
1164
  import { NativeEventEmitter, NativeModules } from 'react-native';
1092
1165
  import { PTREvents } from 'react-native-pointr';
1093
1166
 
1094
- const emitter = new NativeEventEmitter(NativeModules.PTRNativePointrLibrary);
1167
+ const emitter = new NativeEventEmitter(NativeModules.PTRNativeLibrary);
1095
1168
 
1096
1169
  const sub = emitter.addListener(PTREvents.ON_POSITION_CALCULATED, (pos) => {
1097
1170
  console.log(pos);
@@ -1130,12 +1203,12 @@ The `PTRMapWidget` component exposes two event callbacks as props:
1130
1203
 
1131
1204
  ### Declarative (recommended for simple integrations)
1132
1205
 
1133
- Pass `sdkConfig`, `mapWidgetConfig`, and `command` directly as props. No hook or imperative call is needed.
1206
+ Pass `sdkConfig`, `mapWidgetConfig`, and `action` directly as props. No hook or imperative call is needed.
1134
1207
 
1135
1208
  ```tsx
1136
1209
  import React from 'react';
1137
1210
  import { StyleSheet } from 'react-native';
1138
- import { PTRMapWidget, PTRSiteCommand } from 'react-native-pointr';
1211
+ import { PTRMapWidget, PTRFocusMapAction } from 'react-native-pointr';
1139
1212
  import type { PTRConfiguration, PTRMapWidgetConfiguration } from 'react-native-pointr';
1140
1213
 
1141
1214
  const SDK_CONFIG: PTRConfiguration = {
@@ -1157,7 +1230,7 @@ export default function MapScreen() {
1157
1230
  style={styles.map}
1158
1231
  sdkConfig={SDK_CONFIG}
1159
1232
  mapWidgetConfig={MAP_CONFIG}
1160
- command={new PTRSiteCommand('<SITE_EXTERNAL_ID>')}
1233
+ action={new PTRFocusMapAction('<SITE_EXTERNAL_ID>')}
1161
1234
  onMapWidgetDidEndLoading={(e) => {
1162
1235
  const { command, error } = e.nativeEvent;
1163
1236
  if (error) console.error(`${command} failed:`, error);
@@ -1185,7 +1258,7 @@ import React, { useState } from 'react';
1185
1258
  import { Text, View, TouchableOpacity, StyleSheet } from 'react-native';
1186
1259
  import {
1187
1260
  PTRMapWidget,
1188
- PTRSiteCommand,
1261
+ PTRFocusMapAction,
1189
1262
  usePointrSdk,
1190
1263
  } from 'react-native-pointr';
1191
1264
  import type { PTRConfiguration } from 'react-native-pointr';
@@ -1218,7 +1291,7 @@ export default function App() {
1218
1291
  {showMap && (
1219
1292
  <PTRMapWidget
1220
1293
  style={StyleSheet.absoluteFill}
1221
- command={new PTRSiteCommand('<SITE_EXTERNAL_ID>')}
1294
+ action={new PTRFocusMapAction('<SITE_EXTERNAL_ID>')}
1222
1295
  />
1223
1296
  )}
1224
1297
  </View>
@@ -1232,113 +1305,6 @@ const styles = StyleSheet.create({
1232
1305
 
1233
1306
  ---
1234
1307
 
1235
- ## Legacy API
1236
-
1237
- The original imperative API is still fully functional. Existing integrations do not need to migrate.
1238
-
1239
- ### `NativeModules.PTRNativePointrLibrary`
1240
-
1241
- All native module methods remain available via `NativeModules`:
1242
-
1243
- ```typescript
1244
- import { NativeModules } from 'react-native';
1245
-
1246
- const { PTRNativePointrLibrary } = NativeModules;
1247
-
1248
- // Initialize
1249
- PTRNativePointrLibrary.initialize('<CLIENT_ID>', '<LICENSE_KEY>', '<BASE_URL>', 3);
1250
-
1251
- // Start
1252
- PTRNativePointrLibrary.start((state: string) => {
1253
- console.log('State:', state);
1254
- });
1255
-
1256
- // Stop
1257
- PTRNativePointrLibrary.stop();
1258
-
1259
- // Permissions
1260
- PTRNativePointrLibrary.requestPermissions();
1261
- PTRNativePointrLibrary.shouldRequestPermissionsAtStartup(true);
1262
-
1263
- // Position
1264
- PTRNativePointrLibrary.getCurrentLocation((location: any) => {
1265
- if (location) console.log(location);
1266
- });
1267
-
1268
- // Map widget configuration
1269
- PTRNativePointrLibrary.setPointrMapWidgetConfiguration(
1270
- JSON.stringify({ isExitButtonEnabled: false })
1271
- );
1272
-
1273
- // POIs
1274
- const pois = await PTRNativePointrLibrary.getPois('<SITE_ID>');
1275
-
1276
- // My car
1277
- PTRNativePointrLibrary.isMyCarMarked((error: any) => {
1278
- if (!error) console.log('Car is marked');
1279
- });
1280
- ```
1281
-
1282
- **Native start state strings:**
1283
-
1284
- | Value | Meaning |
1285
- |-------|---------|
1286
- | `"running"` | SDK running successfully |
1287
- | `"failed registration"` | Registration failed |
1288
- | `"failed validation"` | Validation failed |
1289
- | `"failed invalid deep link url"` | Invalid deep link URL |
1290
- | `"failed no internet"` | No internet connection |
1291
- | `"off"` | SDK is off |
1292
-
1293
- ---
1294
-
1295
- ### `showMapWidget(reactTag, command)`
1296
-
1297
- Dispatches a command directly by numeric native view tag.
1298
-
1299
- ```typescript
1300
- import { showMapWidget } from 'react-native-pointr';
1301
- import { findNodeHandle } from 'react-native';
1302
-
1303
- const reactTag = findNodeHandle(mapRef.current);
1304
- if (reactTag) {
1305
- showMapWidget(reactTag, new PTRSiteCommand('<SITE_ID>'));
1306
- }
1307
- ```
1308
-
1309
- ---
1310
-
1311
- ### `getPois(siteId)`
1312
-
1313
- ```typescript
1314
- import { getPois } from 'react-native-pointr';
1315
-
1316
- const pois = await getPois('<SITE_EXTERNAL_ID>');
1317
- ```
1318
-
1319
- ---
1320
-
1321
- ### Legacy command imports
1322
-
1323
- ```typescript
1324
- import {
1325
- LegacyPTRCommand,
1326
- LegacyPTRSiteCommand,
1327
- LegacyPTRBuildingCommand,
1328
- LegacyPTRLevelCommand,
1329
- LegacyPTRPoiCommand,
1330
- LegacyPTRPathCommand,
1331
- LegacyPTRStaticPathCommand,
1332
- LegacyPTRStaticWayfindingCommand,
1333
- LegacyPTRMarkMyCarLevelCommand,
1334
- LegacyPTRMarkMyCarSiteCommand,
1335
- LegacyPTRShowMyCarSiteCommand,
1336
- LegacyPTRStartAndFocusCommand,
1337
- } from 'react-native-pointr';
1338
- ```
1339
-
1340
- ---
1341
-
1342
1308
  ## Error Handling
1343
1309
 
1344
1310
  ### Common errors
@@ -1348,8 +1314,8 @@ import {
1348
1314
  | `"Pointr SDK is not initialized. Call initialize() first."` | `start()` or other methods called before `initialize()` | Call `pointrSdk.initialize(config)` first |
1349
1315
  | `"Pointr SDK is not started. Call start() first."` | SDK method called before `start()` completes | Wait for `isStarted` / `PTRState.RUNNING` |
1350
1316
  | `"Pointr SDK is already initialized."` | `initialize()` called twice on the same singleton | Guard with `pointrSdk.isInitialized()` |
1351
- | `"Map widget reference is required."` | `executeMapCommand` called with a null or unmounted ref | Ensure the ref is attached and the component is mounted |
1352
- | `"Invalid map command provided."` | `executeMapCommand` called with a command missing a `type` | Use a proper `PTRCommand` subclass |
1317
+ | `"Map widget reference is required."` | `executeMapAction` called with a null or unmounted ref | Ensure the ref is attached and the component is mounted |
1318
+ | `"Invalid map command provided."` | `executeMapAction` called with an action missing a `type` | Use a proper `PTRAction` subclass |
1353
1319
 
1354
1320
  ### Best practices
1355
1321
 
@@ -1363,3 +1329,6 @@ import {
1363
1329
  ## License
1364
1330
 
1365
1331
  See the LICENSE file in the package root.
1332
+
1333
+
1334
+