@mappedin/blue-dot 6.0.1-beta.55 → 6.0.1-beta.57

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,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../packages/common/pubsub.ts", "../../src/blue-dot.ts"],
4
+ "sourcesContent": ["/**\n * Generic PubSub class implementing the Publish-Subscribe pattern for event handling.\n *\n * @template EVENT_PAYLOAD - The type of the event payload.\n * @template EVENT - The type of the event.\n */\nexport class PubSub<EVENT_PAYLOAD, EVENT extends keyof EVENT_PAYLOAD = keyof EVENT_PAYLOAD> {\n\t/**\n\t * @private\n\t * @internal\n\t */\n\tprivate _subscribers: any = {};\n\t/**\n\t * @private\n\t * @internal\n\t */\n\tprivate _destroyed = false;\n\n\t/**\n\t * @private\n\t * @internal\n\t */\n\tpublish<EVENT_NAME extends EVENT>(eventName: EVENT_NAME, data?: EVENT_PAYLOAD[EVENT_NAME]) {\n\t\tif (!this._subscribers || !this._subscribers[eventName] || this._destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._subscribers[eventName]!.forEach(function (fn) {\n\t\t\tif (typeof fn !== 'function') {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfn(data);\n\t\t});\n\t}\n\n\t/**\n\t * Subscribe a function to an event.\n\t *\n\t * @param eventName An event name which, when fired, will call the provided\n\t * function.\n\t * @param fn A callback that gets called when the corresponding event is fired. The\n\t * callback will get passed an argument with a type that's one of event payloads.\n\t * @example\n\t * // Subscribe to the 'click' event\n\t * const handler = (event) => {\n\t * const { coordinate } = event;\n\t * const { latitude, longitude } = coordinate;\n\t * \tconsole.log(`Map was clicked at ${latitude}, ${longitude}`);\n\t * };\n\t * map.on('click', handler);\n\t */\n\ton<EVENT_NAME extends EVENT>(\n\t\teventName: EVENT_NAME,\n\t\tfn: (\n\t\t\tpayload: EVENT_PAYLOAD[EVENT_NAME] extends {\n\t\t\t\tdata: null;\n\t\t\t}\n\t\t\t\t? EVENT_PAYLOAD[EVENT_NAME]['data']\n\t\t\t\t: EVENT_PAYLOAD[EVENT_NAME],\n\t\t) => void,\n\t) {\n\t\tif (!this._subscribers || this._destroyed) {\n\t\t\tthis._subscribers = {};\n\t\t}\n\t\tthis._subscribers[eventName] = this._subscribers[eventName] || [];\n\t\tthis._subscribers[eventName]!.push(fn);\n\t}\n\n\t/**\n\t * Unsubscribe a function previously subscribed with {@link on}\n\t *\n\t * @param eventName An event name to which the provided function was previously\n\t * subscribed.\n\t * @param fn A function that was previously passed to {@link on}. The function must\n\t * have the same reference as the function that was subscribed.\n\t * @example\n\t * // Unsubscribe from the 'click' event\n\t * const handler = (event) => {\n\t * \tconsole.log('Map was clicked', event);\n\t * };\n\t * map.off('click', handler);\n\t */\n\toff<EVENT_NAME extends EVENT>(\n\t\teventName: EVENT_NAME,\n\t\tfn: (\n\t\t\tpayload: EVENT_PAYLOAD[EVENT_NAME] extends {\n\t\t\t\tdata: null;\n\t\t\t}\n\t\t\t\t? EVENT_PAYLOAD[EVENT_NAME]['data']\n\t\t\t\t: EVENT_PAYLOAD[EVENT_NAME],\n\t\t) => void,\n\t) {\n\t\tif (!this._subscribers || this._subscribers[eventName] == null || this._destroyed) {\n\t\t\treturn;\n\t\t}\n\t\tconst itemIdx = this._subscribers[eventName]!.indexOf(fn);\n\n\t\tif (itemIdx !== -1) {\n\t\t\tthis._subscribers[eventName]!.splice(itemIdx, 1);\n\t\t}\n\t}\n\t/**\n\t * @private\n\t * @internal\n\t */\n\tdestroy() {\n\t\tthis._destroyed = true;\n\t\tthis._subscribers = {};\n\t}\n}\n", "import { PubSub } from '@packages/internal/common/pubsub';\nimport type { MapView } from '@mappedin/mappedin-js';\nimport type {\n\tBlueDotEventPayloads,\n\tBlueDotOptions,\n\tBlueDotPositionUpdate,\n\tBlueDotState,\n\tFollowCameraOptions,\n\tFollowMode,\n} from './types';\n\n/**\n * Show a Blue Dot indicating the device's position on the map.\n *\n * @example\n * ```ts\n * import { show3dMap } from '@mappedin/mappedin-js';\n * import { BlueDot } from '@mappedin/blue-dot';\n *\n * const mapView = await show3dMap(...);\n *\n * // Enable BlueDot\n * new BlueDot(mapView).enable();\n *\n * // Option 1: Listen for position updates from the device\n * mapView.BlueDot.on('position-update', (position) => {\n * console.log('User position:', position);\n * });\n *\n * // Option 2: Update position manually\n * new BlueDot(mapView).update({ latitude, longitude, accuracy, floorOrFloorId });\n *\n * ```\n */\nexport class BlueDot {\n\t#pubsub = new PubSub<BlueDotEventPayloads>();\n\t#mapView: MapView;\n\n\t/**\n\t * Create a new {@link BlueDot} instance.\n\t */\n\tconstructor(mapView: MapView) {\n\t\tthis.#mapView = mapView;\n\t\tthis.#mapView.__BlueDot.on('blue-dot-position-error', e => {\n\t\t\tthis.#pubsub.publish('error', e);\n\t\t});\n\t\tthis.#mapView.__BlueDot.on('blue-dot-position-update', e => {\n\t\t\tthis.#pubsub.publish('position-update', e);\n\t\t});\n\t\tthis.#mapView.__BlueDot.on('blue-dot-state-change', e => {\n\t\t\tthis.#pubsub.publish('state-change', e);\n\t\t});\n\t\tthis.#mapView.__BlueDot.on('blue-dot-follow-change', e => {\n\t\t\tthis.#pubsub.publish('follow-change', e);\n\t\t});\n\t\tthis.#mapView.__BlueDot.on('click', e => {\n\t\t\tthis.#pubsub.publish('click', e);\n\t\t});\n\t\tthis.#mapView.__BlueDot.on('hover', () => {\n\t\t\tthis.#pubsub.publish('hover');\n\t\t});\n\t}\n\n\t/**\n\t * The current state of the BlueDot. Can be 'hidden', 'active', 'inactive', or 'disabled'.\n\t * Listen for state changes using the 'state-change' event.\n\t *\n\t * @example\n\t * mapView.BlueDot.on('state-change', ({ state }) => {\n\t * if (state === 'active') {\n\t * // BlueDot is visible and tracking\n\t * }\n\t * });\n\t */\n\tget state(): BlueDotState {\n\t\treturn this.#mapView.__BlueDot.state;\n\t}\n\n\t/**\n\t * Whether the BlueDot is currently following the user (camera follow mode).\n\t */\n\tget following() {\n\t\treturn this.#mapView.__BlueDot.following;\n\t}\n\n\t/**\n\t * The direction the user is facing in degrees from north clockwise.\n\t * @see https://developer.mozilla.org/en-US/docs/Web/API/GeolocationCoordinates/heading\n\t */\n\tget heading() {\n\t\treturn this.#mapView.__BlueDot.heading;\n\t}\n\n\t/**\n\t * The accuracy of the current position in metres.\n\t */\n\tget accuracy() {\n\t\treturn this.#mapView.__BlueDot.accuracy;\n\t}\n\n\t/**\n\t * The coordinate of the current position.\n\t */\n\tget coordinate() {\n\t\treturn this.#mapView.__BlueDot.coordinate;\n\t}\n\n\t/**\n\t * The floor the Blue Dot is currently on. If undefined, the Blue Dot will appear on every floor.\n\t */\n\tget floor() {\n\t\treturn this.#mapView.__BlueDot.floor;\n\t}\n\n\t/**\n\t * Enable the Blue Dot. It will be hidden until a position is received either from the browser or by calling {@link BlueDot.update}.\n\t * @param options - The options to setup the Blue Dot (see {@link BlueDotOptions}).\n\t *\n\t * @example Enable with default options\n\t * mapView.BlueDot.enable();\n\t *\n\t * @example Enable with custom color and accuracy ring\n\t * mapView.BlueDot.enable({ color: '#00ff00', accuracyRing: { color: '#00ff00', opacity: 0.2 } });\n\t *\n\t * @see See the [BlueDot Guide](https://developer.mappedin.com/web-sdk/blue-dot) for more information.\n\t */\n\tenable = (options?: BlueDotOptions) => {\n\t\tthis.#mapView.__BlueDot.enable(options);\n\t};\n\n\t/**\n\t * Disable the Blue Dot. It will be hidden and no longer update.\n\t */\n\tdisable = () => {\n\t\tthis.#mapView.__BlueDot.disable();\n\t};\n\n\ton: PubSub<BlueDotEventPayloads>['on'] = (eventName, fn) => {\n\t\tthis.#pubsub.on(eventName, fn);\n\t};\n\n\toff: PubSub<BlueDotEventPayloads>['off'] = (eventName, fn) => {\n\t\tthis.#pubsub.off(eventName, fn);\n\t};\n\n\t/**\n\t * Enable or disable the devices's geolocation listener to automatically position the Blue Dot.\n\t * If enabled, the device will request permission to access the user's precise location.\n\t * @param watch - Whether to enable or disable the listener.\n\t */\n\twatchDevicePosition = (watch = true) => {\n\t\tthis.#mapView.__BlueDot.watchDevicePosition(watch);\n\t};\n\n\t/**\n\t * Manually override some position properties of the Blue Dot.\n\t * Accepts a full GeolocationPosition object or a partial {@link BlueDotPositionUpdate} object.\n\t * @example Manually set the accuracy and heading\n\t * ```ts\n\t * api.BlueDot.update({ accuracy: 10, heading: 90 });\n\t * ```\n\t * @example Reset accuracy and heading to device values\n\t * ```ts\n\t * api.BlueDot.update({ accuracy: 'device', heading: 'device' });\n\t * ```\n\t */\n\tupdate = (position: BlueDotPositionUpdate) => {\n\t\tthis.#mapView.__BlueDot.update(position);\n\t};\n\n\t/**\n\t * Set the camera to follow the BlueDot in various modes. User interaction will cancel following automatically.\n\t * @param mode The follow mode ('position-only', 'position-and-heading', 'position-and-path-direction', or false to disable).\n\t * @param cameraOptions Optional camera options (zoom, pitch, etc.).\n\t *\n\t * @example\n\t * mapView.BlueDot.follow('position-and-heading', { zoomLevel: 21, pitch: 45 });\n\t */\n\tfollow = (mode: FollowMode, cameraOptions?: FollowCameraOptions) => {\n\t\tthis.#mapView.__BlueDot.follow(mode, cameraOptions);\n\t};\n\n\tdestroy = () => {\n\t\tthis.#pubsub.destroy();\n\t};\n}\n"],
5
+ "mappings": ";;;;AAMO,IAAM,SAAN,MAAqF;AAAA,EAN5F,OAM4F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAKnF,eAAoB,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAKrB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA,EAMrB,QAAkC,WAAuB,MAAkC;AAC1F,QAAI,CAAC,KAAK,gBAAgB,CAAC,KAAK,aAAa,SAAS,KAAK,KAAK,YAAY;AAC3E;AAAA,IACD;AAEA,SAAK,aAAa,SAAS,EAAG,QAAQ,SAAU,IAAI;AACnD,UAAI,OAAO,OAAO,YAAY;AAC7B;AAAA,MACD;AACA,SAAG,IAAI;AAAA,IACR,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,GACC,WACA,IAOC;AACD,QAAI,CAAC,KAAK,gBAAgB,KAAK,YAAY;AAC1C,WAAK,eAAe,CAAC;AAAA,IACtB;AACA,SAAK,aAAa,SAAS,IAAI,KAAK,aAAa,SAAS,KAAK,CAAC;AAChE,SAAK,aAAa,SAAS,EAAG,KAAK,EAAE;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,IACC,WACA,IAOC;AACD,QAAI,CAAC,KAAK,gBAAgB,KAAK,aAAa,SAAS,KAAK,QAAQ,KAAK,YAAY;AAClF;AAAA,IACD;AACA,UAAM,UAAU,KAAK,aAAa,SAAS,EAAG,QAAQ,EAAE;AAExD,QAAI,YAAY,IAAI;AACnB,WAAK,aAAa,SAAS,EAAG,OAAO,SAAS,CAAC;AAAA,IAChD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU;AACT,SAAK,aAAa;AAClB,SAAK,eAAe,CAAC;AAAA,EACtB;AACD;;;AC3EO,IAAM,UAAN,MAAc;AAAA,EAlCrB,OAkCqB;AAAA;AAAA;AAAA,EACpB,UAAU,IAAI,OAA6B;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,SAAkB;AAC7B,SAAK,WAAW;AAChB,SAAK,SAAS,UAAU,GAAG,2BAA2B,OAAK;AAC1D,WAAK,QAAQ,QAAQ,SAAS,CAAC;AAAA,IAChC,CAAC;AACD,SAAK,SAAS,UAAU,GAAG,4BAA4B,OAAK;AAC3D,WAAK,QAAQ,QAAQ,mBAAmB,CAAC;AAAA,IAC1C,CAAC;AACD,SAAK,SAAS,UAAU,GAAG,yBAAyB,OAAK;AACxD,WAAK,QAAQ,QAAQ,gBAAgB,CAAC;AAAA,IACvC,CAAC;AACD,SAAK,SAAS,UAAU,GAAG,0BAA0B,OAAK;AACzD,WAAK,QAAQ,QAAQ,iBAAiB,CAAC;AAAA,IACxC,CAAC;AACD,SAAK,SAAS,UAAU,GAAG,SAAS,OAAK;AACxC,WAAK,QAAQ,QAAQ,SAAS,CAAC;AAAA,IAChC,CAAC;AACD,SAAK,SAAS,UAAU,GAAG,SAAS,MAAM;AACzC,WAAK,QAAQ,QAAQ,OAAO;AAAA,IAC7B,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,IAAI,QAAsB;AACzB,WAAO,KAAK,SAAS,UAAU;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,YAAY;AACf,WAAO,KAAK,SAAS,UAAU;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,UAAU;AACb,WAAO,KAAK,SAAS,UAAU;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,WAAW;AACd,WAAO,KAAK,SAAS,UAAU;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,aAAa;AAChB,WAAO,KAAK,SAAS,UAAU;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,QAAQ;AACX,WAAO,KAAK,SAAS,UAAU;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,SAAS,wBAAC,YAA6B;AACtC,SAAK,SAAS,UAAU,OAAO,OAAO;AAAA,EACvC,GAFS;AAAA;AAAA;AAAA;AAAA,EAOT,UAAU,6BAAM;AACf,SAAK,SAAS,UAAU,QAAQ;AAAA,EACjC,GAFU;AAAA,EAIV,KAAyC,wBAAC,WAAW,OAAO;AAC3D,SAAK,QAAQ,GAAG,WAAW,EAAE;AAAA,EAC9B,GAFyC;AAAA,EAIzC,MAA2C,wBAAC,WAAW,OAAO;AAC7D,SAAK,QAAQ,IAAI,WAAW,EAAE;AAAA,EAC/B,GAF2C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAS3C,sBAAsB,wBAAC,QAAQ,SAAS;AACvC,SAAK,SAAS,UAAU,oBAAoB,KAAK;AAAA,EAClD,GAFsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBtB,SAAS,wBAAC,aAAoC;AAC7C,SAAK,SAAS,UAAU,OAAO,QAAQ;AAAA,EACxC,GAFS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYT,SAAS,wBAAC,MAAkB,kBAAwC;AACnE,SAAK,SAAS,UAAU,OAAO,MAAM,aAAa;AAAA,EACnD,GAFS;AAAA,EAIT,UAAU,6BAAM;AACf,SAAK,QAAQ,QAAQ;AAAA,EACtB,GAFU;AAGX;",
6
+ "names": []
7
+ }
@@ -0,0 +1,4 @@
1
+ export { useBlueDot } from './rn/use-blue-dot';
2
+ export { useBlueDotEvent } from './rn/use-blue-dot-events';
3
+ export type { UseBlueDotResult, BlueDotExtensionState } from './rn/use-blue-dot';
4
+ import './rn/extension-augmentation';
@@ -0,0 +1,295 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+
4
+ // src/rn/use-blue-dot.ts
5
+ import { useCallback as useCallback2, useContext as useContext2, useRef } from "react";
6
+ import { MappedinContext as MappedinContext2 } from "@mappedin/react-native-sdk";
7
+
8
+ // src/rn/use-blue-dot-events.ts
9
+ import { useCallback, useContext } from "react";
10
+ import {
11
+ MappedinContext,
12
+ useEventCallback,
13
+ createEventSetupScript,
14
+ createEventCleanupScript
15
+ } from "@mappedin/react-native-sdk";
16
+
17
+ // src/rn/use-blue-dot-registration.ts
18
+ import { useRegisterExtension } from "@mappedin/react-native-sdk";
19
+
20
+ // src/rn/extension-source.ts
21
+ var EXTENSION_SOURCE_PLACEHOLDER = `
22
+ // Define require function that uses bridge.modules for external dependencies
23
+ globalThis.require = globalThis.require || ((id) => {
24
+ if (window.bridge?.modules?.[id]) {
25
+ return window.bridge.modules[id];
26
+ }
27
+ throw new Error('Module not found: ' + id);
28
+ });
29
+
30
+ "use strict";var BlueDot=(()=>{var a=Object.defineProperty;var A=Object.getOwnPropertyDescriptor;var f=Object.getOwnPropertyNames;var B=Object.prototype.hasOwnProperty;var c=o=>{throw TypeError(o)};var V=(o,t,e)=>t in o?a(o,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):o[t]=e;var l=(o,t)=>a(o,"name",{value:t,configurable:!0});var T=(o,t)=>{for(var e in t)a(o,e,{get:t[e],enumerable:!0})},y=(o,t,e,E)=>{if(t&&typeof t=="object"||typeof t=="function")for(let _ of f(t))!B.call(o,_)&&_!==e&&a(o,_,{get:()=>t[_],enumerable:!(E=A(t,_))||E.enumerable});return o};var P=o=>y(a({},"__esModule",{value:!0}),o);var r=(o,t,e)=>V(o,typeof t!="symbol"?t+"":t,e),D=(o,t,e)=>t.has(o)||c("Cannot "+e);var s=(o,t,e)=>(D(o,t,"read from private field"),e?e.call(o):t.get(o)),d=(o,t,e)=>t.has(o)?c("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(o):t.set(o,e),N=(o,t,e,E)=>(D(o,t,"write to private field"),E?E.call(o,e):t.set(o,e),e);var w={};T(w,{BlueDot:()=>h});var p=class p{constructor(){r(this,"_subscribers",{});r(this,"_destroyed",!1)}publish(t,e){!this._subscribers||!this._subscribers[t]||this._destroyed||this._subscribers[t].forEach(function(E){typeof E=="function"&&E(e)})}on(t,e){(!this._subscribers||this._destroyed)&&(this._subscribers={}),this._subscribers[t]=this._subscribers[t]||[],this._subscribers[t].push(e)}off(t,e){if(!this._subscribers||this._subscribers[t]==null||this._destroyed)return;let E=this._subscribers[t].indexOf(e);E!==-1&&this._subscribers[t].splice(E,1)}destroy(){this._destroyed=!0,this._subscribers={}}};l(p,"PubSub");var n=p;var u,i,b=class b{constructor(t){d(this,u,new n);d(this,i);r(this,"enable",l(t=>{s(this,i).__BlueDot.enable(t)},"enable"));r(this,"disable",l(()=>{s(this,i).__BlueDot.disable()},"disable"));r(this,"on",l((t,e)=>{s(this,u).on(t,e)},"on"));r(this,"off",l((t,e)=>{s(this,u).off(t,e)},"off"));r(this,"watchDevicePosition",l((t=!0)=>{s(this,i).__BlueDot.watchDevicePosition(t)},"watchDevicePosition"));r(this,"update",l(t=>{s(this,i).__BlueDot.update(t)},"update"));r(this,"follow",l((t,e)=>{s(this,i).__BlueDot.follow(t,e)},"follow"));r(this,"destroy",l(()=>{s(this,u).destroy()},"destroy"));N(this,i,t),s(this,i).__BlueDot.on("blue-dot-position-error",e=>{s(this,u).publish("error",e)}),s(this,i).__BlueDot.on("blue-dot-position-update",e=>{s(this,u).publish("position-update",e)}),s(this,i).__BlueDot.on("blue-dot-state-change",e=>{s(this,u).publish("state-change",e)}),s(this,i).__BlueDot.on("blue-dot-follow-change",e=>{s(this,u).publish("follow-change",e)}),s(this,i).__BlueDot.on("click",e=>{s(this,u).publish("click",e)}),s(this,i).__BlueDot.on("hover",()=>{s(this,u).publish("hover")})}get state(){return s(this,i).__BlueDot.state}get following(){return s(this,i).__BlueDot.following}get heading(){return s(this,i).__BlueDot.heading}get accuracy(){return s(this,i).__BlueDot.accuracy}get coordinate(){return s(this,i).__BlueDot.coordinate}get floor(){return s(this,i).__BlueDot.floor}};u=new WeakMap,i=new WeakMap,l(b,"BlueDot");var h=b;return P(w);})();
31
+ //# sourceMappingURL=blue-dot.iife.js.map
32
+
33
+
34
+ // Register the extension
35
+ if (window.bridge && window.bridge.extensions) {
36
+ try {
37
+ window.bridge.extensions.register({ name: 'blue-dot', package: { Extension: BlueDot.BlueDot } });
38
+ if (window.rnDebug) window.rnDebug('BlueDot Extension Registered');
39
+ } catch(e) {
40
+ if (window.rnDebug) window.rnDebug('Failed to register blue-dot extension: ' + e.message);
41
+ }
42
+ } else {
43
+ if (window.rnDebug) window.rnDebug('Bridge or extensions not available for registration');
44
+ }`;
45
+ function getRegistrationScript() {
46
+ return EXTENSION_SOURCE_PLACEHOLDER;
47
+ }
48
+ __name(getRegistrationScript, "getRegistrationScript");
49
+
50
+ // ../packages/common/Mappedin.Logger.ts
51
+ var MI_ERROR_LABEL = "[MappedinJS]";
52
+ function createLogger(name = "", { prefix = MI_ERROR_LABEL } = {}) {
53
+ const label = `${prefix}${name ? `-${name}` : ""}`;
54
+ const rnDebug = /* @__PURE__ */ __name((type, args) => {
55
+ if (typeof window !== "undefined" && window.rnDebug) {
56
+ const processed = args.map((arg) => {
57
+ if (arg instanceof Error && arg.stack) {
58
+ return `${arg.message}
59
+ ${arg.stack}`;
60
+ }
61
+ return arg;
62
+ });
63
+ window.rnDebug(`${name} ${type}: ${processed.join(" ")}`);
64
+ }
65
+ }, "rnDebug");
66
+ return {
67
+ logState: false ? 3 /* SILENT */ : 0 /* LOG */,
68
+ log(...args) {
69
+ if (this.logState <= 0 /* LOG */) {
70
+ console.log(label, ...args);
71
+ rnDebug("log", args);
72
+ }
73
+ },
74
+ warn(...args) {
75
+ if (this.logState <= 1 /* WARN */) {
76
+ console.warn(label, ...args);
77
+ rnDebug("warn", args);
78
+ }
79
+ },
80
+ error(...args) {
81
+ if (this.logState <= 2 /* ERROR */) {
82
+ console.error(label, ...args);
83
+ rnDebug("error", args);
84
+ }
85
+ },
86
+ // It's a bit tricky to prepend [MappedinJs] to assert and time because of how the output is structured in the console, so it is left out for simplicity
87
+ assert(...args) {
88
+ console.assert(...args);
89
+ },
90
+ time(label2) {
91
+ console.time(label2);
92
+ },
93
+ timeEnd(label2) {
94
+ console.timeEnd(label2);
95
+ },
96
+ setLevel(level) {
97
+ if (0 /* LOG */ <= level && level <= 3 /* SILENT */) {
98
+ this.logState = level;
99
+ }
100
+ }
101
+ };
102
+ }
103
+ __name(createLogger, "createLogger");
104
+ var Logger = createLogger();
105
+ var Mappedin_Logger_default = Logger;
106
+
107
+ // src/rn/use-blue-dot-registration.ts
108
+ function useBlueDotRegistration() {
109
+ useRegisterExtension({
110
+ extensionName: "blue-dot",
111
+ getRegistrationScript,
112
+ logger: {
113
+ log: /* @__PURE__ */ __name((message) => Mappedin_Logger_default.log(message), "log"),
114
+ error: /* @__PURE__ */ __name((message, error) => Mappedin_Logger_default.error(message, error), "error")
115
+ }
116
+ });
117
+ }
118
+ __name(useBlueDotRegistration, "useBlueDotRegistration");
119
+
120
+ // src/rn/use-blue-dot-events.ts
121
+ function useBlueDotEvent(eventName, callback) {
122
+ if (typeof eventName !== "string" || eventName.length === 0) {
123
+ throw new Error("Event parameter must be a non-empty string");
124
+ }
125
+ if (typeof callback !== "function") {
126
+ throw new Error("Callback parameter must be a function");
127
+ }
128
+ const context = useContext(MappedinContext);
129
+ const { extensions, mapData } = context;
130
+ if (!mapData) {
131
+ throw new Error("Map data is not available");
132
+ }
133
+ useBlueDotRegistration();
134
+ const extensionRegistrationState = extensions?.["blue-dot"]?.registrationState || "unregistered";
135
+ const extensionIsReady = extensionRegistrationState === "registered";
136
+ const processedCallback = useCallback(
137
+ (payload) => {
138
+ try {
139
+ callback(payload);
140
+ } catch (error) {
141
+ console.error(`Error in blue dot event callback for ${String(eventName)}:`, error);
142
+ }
143
+ },
144
+ [eventName, callback]
145
+ );
146
+ useEventCallback({
147
+ eventKey: `blue-dot:${String(eventName)}`,
148
+ callback: processedCallback,
149
+ setupScript: /* @__PURE__ */ __name(() => createEventSetupScript({
150
+ extensionName: "blue-dot",
151
+ eventName
152
+ }), "setupScript"),
153
+ cleanupScript: /* @__PURE__ */ __name(() => createEventCleanupScript({
154
+ extensionName: "blue-dot",
155
+ eventName
156
+ }), "cleanupScript"),
157
+ shouldInject: extensionIsReady
158
+ });
159
+ }
160
+ __name(useBlueDotEvent, "useBlueDotEvent");
161
+
162
+ // src/rn/use-blue-dot.ts
163
+ function useBlueDot() {
164
+ const context = useContext2(MappedinContext2);
165
+ const { bridge, extensions, updateExtensionState } = context;
166
+ useBlueDotRegistration();
167
+ const extensionState = extensions["blue-dot"];
168
+ const registrationState = extensionState?.registrationState || "unregistered";
169
+ const isReady = registrationState === "registered";
170
+ const isEnabled = extensionState?.isEnabled || false;
171
+ const state = extensionState?.state || "hidden";
172
+ const following = extensionState?.following || false;
173
+ const position = extensionState?.position;
174
+ const floor = extensionState?.floor;
175
+ const accuracy = extensionState?.accuracy;
176
+ const heading = extensionState?.heading;
177
+ const extensionsRef = useRef(extensions);
178
+ extensionsRef.current = extensions;
179
+ useBlueDotEvent(
180
+ "position-update",
181
+ useCallback2(
182
+ (event) => {
183
+ updateExtensionState("blue-dot", (prev) => ({
184
+ ...prev,
185
+ position: event.coordinate,
186
+ floor: event.floor,
187
+ accuracy: event.accuracy ?? void 0,
188
+ heading: event.heading ?? void 0
189
+ }));
190
+ },
191
+ [updateExtensionState]
192
+ )
193
+ );
194
+ useBlueDotEvent(
195
+ "state-change",
196
+ useCallback2(
197
+ (event) => {
198
+ updateExtensionState("blue-dot", (prev) => ({
199
+ ...prev,
200
+ state: event.state
201
+ }));
202
+ },
203
+ [updateExtensionState]
204
+ )
205
+ );
206
+ useBlueDotEvent(
207
+ "follow-change",
208
+ useCallback2(
209
+ (event) => {
210
+ updateExtensionState("blue-dot", (prev) => ({
211
+ ...prev,
212
+ following: event.following
213
+ }));
214
+ },
215
+ [updateExtensionState]
216
+ )
217
+ );
218
+ const callExtensionMethod = useCallback2(
219
+ async (method, args = []) => {
220
+ if (!bridge?.isReady) {
221
+ throw new Error("Bridge is not ready. Ensure the WebView is loaded.");
222
+ }
223
+ return await bridge.instruct({
224
+ type: "extension",
225
+ payload: {
226
+ name: "blue-dot",
227
+ method,
228
+ args
229
+ }
230
+ });
231
+ },
232
+ [bridge]
233
+ );
234
+ const enable = useCallback2(
235
+ async (options) => {
236
+ const currentExtensionState = extensionsRef.current?.["blue-dot"];
237
+ const currentIsEnabled = currentExtensionState?.isEnabled || false;
238
+ if (currentIsEnabled) {
239
+ return;
240
+ }
241
+ await callExtensionMethod("enable", [options]);
242
+ updateExtensionState("blue-dot", (prev) => ({ ...prev, isEnabled: true }));
243
+ },
244
+ [callExtensionMethod, updateExtensionState]
245
+ );
246
+ const disable = useCallback2(async () => {
247
+ await callExtensionMethod("disable");
248
+ updateExtensionState("blue-dot", {
249
+ registrationState: "unregistered",
250
+ isEnabled: false,
251
+ state: "hidden",
252
+ position: void 0,
253
+ floor: void 0,
254
+ following: false,
255
+ accuracy: void 0,
256
+ heading: void 0
257
+ });
258
+ }, [callExtensionMethod, updateExtensionState]);
259
+ const update = useCallback2(
260
+ async (positionUpdate) => {
261
+ return await callExtensionMethod("update", [positionUpdate]);
262
+ },
263
+ [callExtensionMethod]
264
+ );
265
+ const follow = useCallback2(
266
+ async (mode, options) => {
267
+ return await callExtensionMethod("follow", [mode, options]);
268
+ },
269
+ [callExtensionMethod]
270
+ );
271
+ const unfollow = useCallback2(async () => {
272
+ return await callExtensionMethod("unfollow");
273
+ }, [callExtensionMethod]);
274
+ return {
275
+ isReady,
276
+ isEnabled,
277
+ state,
278
+ position,
279
+ floor,
280
+ following,
281
+ accuracy,
282
+ heading,
283
+ enable,
284
+ disable,
285
+ update,
286
+ follow,
287
+ unfollow
288
+ };
289
+ }
290
+ __name(useBlueDot, "useBlueDot");
291
+ export {
292
+ useBlueDot,
293
+ useBlueDotEvent
294
+ };
295
+ //# sourceMappingURL=index-rn.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/rn/use-blue-dot.ts", "../../src/rn/use-blue-dot-events.ts", "../../src/rn/use-blue-dot-registration.ts", "../../src/rn/extension-source.ts", "../../../packages/common/Mappedin.Logger.ts"],
4
+ "sourcesContent": ["import { useCallback, useContext, useRef } from 'react';\nimport type { BlueDotOptions, BlueDotPositionUpdate, BlueDotState, FollowMode, FollowCameraOptions } from '../types';\nimport { MappedinContext } from '@mappedin/react-native-sdk';\nimport type { Coordinate, Floor } from '@mappedin/mappedin-js';\nimport { useBlueDotEvent } from './use-blue-dot-events';\nimport { useBlueDotRegistration } from './use-blue-dot-registration';\n\n/**\n * Extension state for Blue Dot that includes the current state and position\n */\nexport interface BlueDotExtensionState {\n\t/**\n\t * Whether the extension is currently enabled\n\t */\n\tisEnabled: boolean;\n\t/**\n\t * The current state of the Blue Dot\n\t */\n\tstate: BlueDotState;\n\t/**\n\t * The current position of the Blue Dot\n\t */\n\tposition?: Coordinate;\n\t/**\n\t * The current floor of the Blue Dot\n\t */\n\tfloor?: Floor;\n\t/**\n\t * Whether the Blue Dot is currently following the user\n\t */\n\tfollowing: boolean;\n\t/**\n\t * The accuracy of the current position in metres\n\t */\n\taccuracy?: number;\n\t/**\n\t * The direction the user is facing in degrees from north clockwise\n\t */\n\theading?: number;\n}\n\n// Blue Dot hook return type\nexport interface UseBlueDotResult {\n\t/**\n\t * Whether the extension is ready and initialized\n\t */\n\tisReady: boolean;\n\t/**\n\t * Whether the extension is currently enabled\n\t */\n\tisEnabled: boolean;\n\t/**\n\t * The current state of the Blue Dot\n\t */\n\tstate: BlueDotState;\n\t/**\n\t * The current position of the Blue Dot\n\t */\n\tposition?: Coordinate;\n\t/**\n\t * The current floor of the Blue Dot\n\t */\n\tfloor?: Floor;\n\t/**\n\t * Whether the Blue Dot is currently following the user\n\t */\n\tfollowing: boolean;\n\t/**\n\t * The accuracy of the current position in metres\n\t */\n\taccuracy?: number;\n\t/**\n\t * The direction the user is facing in degrees from north clockwise\n\t */\n\theading?: number;\n\n\t/**\n\t * Enables Blue Dot with the given options.\n\t * @param options - The options to enable Blue Dot with\n\t * @returns Promise that resolves when enabling is complete\n\t * @see {@link BlueDot.enable}\n\t */\n\tenable(options?: BlueDotOptions): Promise<void>;\n\n\t/**\n\t * Disables the Blue Dot instance and unsubscribes all MapView event listeners.\n\t * @returns Promise that resolves when disabling is complete\n\t * @see {@link BlueDot.disable}\n\t */\n\tdisable(): Promise<void>;\n\n\t/**\n\t * Update the Blue Dot's position manually.\n\t * @param position - The position update options\n\t * @returns Promise that resolves when the update is complete\n\t * @see {@link BlueDot.update}\n\t */\n\tupdate(position: BlueDotPositionUpdate): Promise<void>;\n\n\t/**\n\t * Enable follow mode for the Blue Dot.\n\t * @param mode - The follow mode to enable\n\t * @param options - The follow camera options\n\t * @returns Promise that resolves when follow mode is enabled\n\t * @see {@link BlueDot.follow}\n\t */\n\tfollow(mode: FollowMode, options?: FollowCameraOptions): Promise<void>;\n\n\t/**\n\t * Disable follow mode for the Blue Dot.\n\t * @returns Promise that resolves when follow mode is disabled\n\t * @see {@link BlueDot.unfollow}\n\t */\n\tunfollow(): Promise<void>;\n}\n\n/**\n * React hook for using BlueDot extension in React Native WebView\n *\n * This hook provides an API for interacting with the BlueDot extension:\n * - Uses the shared state system for automatic extension registration\n * - Provides methods for controlling blue dot behavior\n * - Handles bridge communication and error management\n *\n * @returns Hook API object with Blue Dot methods\n *\n * @example\n * ```tsx\n * import { MapView } from '@mappedin/react-native-sdk';\n * import { useBlueDot } from '@mappedin/blue-dot/rn';\n *\n * function MyComponent() {\n * const { enable, isReady, state, following } = useBlueDot();\n *\n * // Use the Blue Dot API\n * React.useEffect(() => {\n * if (isReady) {\n * enable({ radius: 15, color: '#ff0000' });\n * }\n * }, [isReady]);\n * }\n * ```\n */\nexport function useBlueDot(): UseBlueDotResult {\n\tconst context = useContext(MappedinContext);\n\tconst { bridge, extensions, updateExtensionState } = context;\n\n\t// Use registration hook to handle extension registration (no parameters needed)\n\tuseBlueDotRegistration();\n\n\t// Get extension state from context - properly typed now, no casting needed!\n\tconst extensionState = extensions['blue-dot'];\n\tconst registrationState = extensionState?.registrationState || 'unregistered';\n\tconst isReady = registrationState === 'registered'; // Backward compatibility\n\tconst isEnabled = extensionState?.isEnabled || false;\n\tconst state = extensionState?.state || 'hidden';\n\tconst following = extensionState?.following || false;\n\tconst position = extensionState?.position;\n\tconst floor = extensionState?.floor;\n\tconst accuracy = extensionState?.accuracy;\n\tconst heading = extensionState?.heading;\n\n\t// Use ref to maintain stable reference for extensions for memoization\n\tconst extensionsRef = useRef(extensions);\n\n\t// Update ref on each render\n\textensionsRef.current = extensions;\n\n\t// Extension registration is handled by useRegisterExtensionHook\n\n\t// Listen for position-update events to update position data\n\tuseBlueDotEvent(\n\t\t'position-update',\n\t\tuseCallback(\n\t\t\tevent => {\n\t\t\t\t// Update extension state to persist position data - use callback to merge\n\t\t\t\tupdateExtensionState('blue-dot', prev => ({\n\t\t\t\t\t...prev,\n\t\t\t\t\tposition: event.coordinate,\n\t\t\t\t\tfloor: event.floor,\n\t\t\t\t\taccuracy: event.accuracy ?? undefined,\n\t\t\t\t\theading: event.heading ?? undefined,\n\t\t\t\t}));\n\t\t\t},\n\t\t\t[updateExtensionState],\n\t\t),\n\t);\n\n\t// Listen for state-change events to update state\n\tuseBlueDotEvent(\n\t\t'state-change',\n\t\tuseCallback(\n\t\t\tevent => {\n\t\t\t\t// Update extension state to reflect state changes - use callback to merge\n\t\t\t\tupdateExtensionState('blue-dot', prev => ({\n\t\t\t\t\t...prev,\n\t\t\t\t\tstate: event.state,\n\t\t\t\t}));\n\t\t\t},\n\t\t\t[updateExtensionState],\n\t\t),\n\t);\n\n\t// Listen for follow-change events to update following state\n\tuseBlueDotEvent(\n\t\t'follow-change',\n\t\tuseCallback(\n\t\t\tevent => {\n\t\t\t\t// Update extension state to reflect following changes - use callback to merge\n\t\t\t\tupdateExtensionState('blue-dot', prev => ({\n\t\t\t\t\t...prev,\n\t\t\t\t\tfollowing: event.following,\n\t\t\t\t}));\n\t\t\t},\n\t\t\t[updateExtensionState],\n\t\t),\n\t);\n\n\t/**\n\t * Helper function to make extension method calls through the bridge\n\t */\n\tconst callExtensionMethod = useCallback(\n\t\tasync <T = any>(method: string, args: any[] = []): Promise<T> => {\n\t\t\tif (!bridge?.isReady) {\n\t\t\t\tthrow new Error('Bridge is not ready. Ensure the WebView is loaded.');\n\t\t\t}\n\n\t\t\treturn (await bridge.instruct({\n\t\t\t\ttype: 'extension',\n\t\t\t\tpayload: {\n\t\t\t\t\tname: 'blue-dot',\n\t\t\t\t\tmethod,\n\t\t\t\t\targs,\n\t\t\t\t},\n\t\t\t})) as T;\n\t\t},\n\t\t[bridge],\n\t);\n\n\t// Memoize the enable method to prevent unnecessary re-renders\n\tconst enable = useCallback(\n\t\tasync (options?: BlueDotOptions): Promise<void> => {\n\t\t\t// Get current isEnabled state from context using ref to avoid dependency\n\t\t\tconst currentExtensionState = extensionsRef.current?.['blue-dot'];\n\t\t\tconst currentIsEnabled = currentExtensionState?.isEnabled || false;\n\n\t\t\t// Check if already enabled to avoid unnecessary calls\n\t\t\tif (currentIsEnabled) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tawait callExtensionMethod<void>('enable', [options]);\n\n\t\t\t// Update extension state to reflect enabled status - use callback to merge\n\t\t\tupdateExtensionState('blue-dot', prev => ({ ...prev, isEnabled: true }));\n\t\t},\n\t\t[callExtensionMethod, updateExtensionState],\n\t);\n\n\t// Memoize the disable method to prevent unnecessary re-renders\n\tconst disable = useCallback(async (): Promise<void> => {\n\t\tawait callExtensionMethod<void>('disable');\n\n\t\t// Reset all state after disabling - replace entire state in this case\n\t\tupdateExtensionState('blue-dot', {\n\t\t\tregistrationState: 'unregistered',\n\t\t\tisEnabled: false,\n\t\t\tstate: 'hidden',\n\t\t\tposition: undefined,\n\t\t\tfloor: undefined,\n\t\t\tfollowing: false,\n\t\t\taccuracy: undefined,\n\t\t\theading: undefined,\n\t\t});\n\t}, [callExtensionMethod, updateExtensionState]);\n\n\t// Memoize the update method to prevent unnecessary re-renders\n\tconst update = useCallback(\n\t\tasync (positionUpdate: BlueDotPositionUpdate): Promise<void> => {\n\t\t\treturn await callExtensionMethod<void>('update', [positionUpdate]);\n\t\t},\n\t\t[callExtensionMethod],\n\t);\n\n\t// Memoize the follow method to prevent unnecessary re-renders\n\tconst follow = useCallback(\n\t\tasync (mode: FollowMode, options?: FollowCameraOptions): Promise<void> => {\n\t\t\treturn await callExtensionMethod<void>('follow', [mode, options]);\n\t\t},\n\t\t[callExtensionMethod],\n\t);\n\n\t// Memoize the unfollow method to prevent unnecessary re-renders\n\tconst unfollow = useCallback(async (): Promise<void> => {\n\t\treturn await callExtensionMethod<void>('unfollow');\n\t}, [callExtensionMethod]);\n\n\t// Return hook API with Blue Dot methods\n\treturn {\n\t\tisReady,\n\t\tisEnabled,\n\t\tstate,\n\t\tposition,\n\t\tfloor,\n\t\tfollowing,\n\t\taccuracy,\n\t\theading,\n\t\tenable,\n\t\tdisable,\n\t\tupdate,\n\t\tfollow,\n\t\tunfollow,\n\t};\n}\n", "import { useCallback, useContext } from 'react';\nimport {\n\tMappedinContext,\n\tuseEventCallback,\n\tcreateEventSetupScript,\n\tcreateEventCleanupScript,\n} from '@mappedin/react-native-sdk';\nimport type { BlueDotEvents, BlueDotEventPayloads } from '../types';\nimport { useBlueDotRegistration } from './use-blue-dot-registration';\n\n/**\n * React hook for subscribing to BlueDot extension events in React Native WebView\n *\n * This hook provides a React-friendly way to listen for BlueDot events:\n * - Automatically manages event subscription/unsubscription\n * - Handles WebView bridge message routing\n * - Provides type-safe event payload handling\n * - Cleans up listeners on component unmount\n *\n * @param eventName - The name of the BlueDot event to listen for\n * @param callback - The callback function to invoke when the event occurs\n *\n * @example\n * ```tsx\n * import { useBlueDotEvent } from '@mappedin/blue-dot/rn';\n *\n * function MyComponent() {\n * // Listen for position updates\n * useBlueDotEvent('position-update', (event) => {\n * console.log('New position:', event.coordinate);\n * console.log('Floor:', event.floor?.name);\n * console.log('Accuracy:', event.accuracy);\n * });\n *\n * // Listen for state changes\n * useBlueDotEvent('state-change', (event) => {\n * console.log('Blue Dot state changed to:', event.state);\n * console.log('Action that caused change:', event.action);\n * });\n *\n * // Listen for follow mode changes\n * useBlueDotEvent('follow-change', (event) => {\n * console.log('Following:', event.following);\n * console.log('Mode:', event.mode);\n * });\n * }\n * ```\n */\nexport function useBlueDotEvent<K extends BlueDotEvents>(\n\teventName: K,\n\tcallback: (payload: BlueDotEventPayloads[K]) => void,\n): void {\n\t// Parameter validation\n\tif (typeof eventName !== 'string' || eventName.length === 0) {\n\t\tthrow new Error('Event parameter must be a non-empty string');\n\t}\n\n\tif (typeof callback !== 'function') {\n\t\tthrow new Error('Callback parameter must be a function');\n\t}\n\n\tconst context = useContext(MappedinContext);\n\tconst { extensions, mapData } = context;\n\n\tif (!mapData) {\n\t\tthrow new Error('Map data is not available');\n\t}\n\n\t// Use registration hook to ensure extension is registered\n\tuseBlueDotRegistration();\n\n\t// Get extension readiness from context only\n\tconst extensionRegistrationState = extensions?.['blue-dot']?.registrationState || 'unregistered';\n\tconst extensionIsReady = extensionRegistrationState === 'registered';\n\n\t// Create a callback wrapper that handles error catching\n\tconst processedCallback = useCallback(\n\t\t(payload: BlueDotEventPayloads[K]) => {\n\t\t\ttry {\n\t\t\t\t// For Blue Dot events, we don't need complex payload hydration like dynamic-focus\n\t\t\t\t// Call the callback directly with the payload\n\t\t\t\tcallback(payload);\n\t\t\t} catch (error) {\n\t\t\t\t// eslint-disable-next-line\n\t\t\t\tconsole.error(`Error in blue dot event callback for ${String(eventName)}:`, error);\n\t\t\t}\n\t\t},\n\t\t[eventName, callback],\n\t);\n\n\t// Use the shared event callback hook with blue dot specific setup/cleanup\n\tuseEventCallback({\n\t\teventKey: `blue-dot:${String(eventName)}`,\n\t\tcallback: processedCallback,\n\t\tsetupScript: () =>\n\t\t\tcreateEventSetupScript({\n\t\t\t\textensionName: 'blue-dot',\n\t\t\t\teventName: eventName,\n\t\t\t}),\n\t\tcleanupScript: () =>\n\t\t\tcreateEventCleanupScript({\n\t\t\t\textensionName: 'blue-dot',\n\t\t\t\teventName: eventName,\n\t\t\t}),\n\t\tshouldInject: extensionIsReady,\n\t});\n}\n", "import { useRegisterExtension } from '@mappedin/react-native-sdk';\nimport { getRegistrationScript } from './extension-source';\nimport Logger from '@packages/internal/common/Mappedin.Logger';\n\n/**\n * React hook for registering the BlueDot extension with the WebView bridge\n *\n * This hook handles the complete extension registration lifecycle:\n * - Monitors bridge readiness state\n * - Checks if extension is already registered to avoid duplicates\n * - Injects registration script when needed\n * - Updates extension state in shared context\n * - Handles all registration errors gracefully\n *\n * Multiple hooks can use this safely - the registration logic is idempotent\n * and will only register the extension once per bridge lifecycle.\n *\n * @returns void - Hook performs registration as side effect only\n */\nexport function useBlueDotRegistration() {\n\tuseRegisterExtension({\n\t\textensionName: 'blue-dot',\n\t\tgetRegistrationScript,\n\t\tlogger: {\n\t\t\tlog: message => Logger.log(message),\n\t\t\terror: (message, error) => Logger.error(message, error),\n\t\t},\n\t});\n}\n", "// Extension source placeholder - replaced at build time\nconst EXTENSION_SOURCE_PLACEHOLDER = `INJECT_SCRIPT_HERE`;\n\n/**\n * Returns the extension registration script\n * This function's return value is replaced at build time with the actual IIFE content\n * @returns JavaScript code string for extension registration\n */\nexport function getRegistrationScript(): string {\n\treturn EXTENSION_SOURCE_PLACEHOLDER;\n}\n", "/* eslint-disable no-console*/\nexport const MI_DEBUG_KEY = 'mi-debug';\nexport const MI_ERROR_LABEL = '[MappedinJS]';\n\nexport enum E_SDK_LOG_LEVEL {\n\tLOG,\n\tWARN,\n\tERROR,\n\tSILENT,\n}\n\nexport function createLogger(name = '', { prefix = MI_ERROR_LABEL } = {}) {\n\tconst label = `${prefix}${name ? `-${name}` : ''}`;\n\n\tconst rnDebug = (type: 'log' | 'warn' | 'error', args: any[]) => {\n\t\tif (typeof window !== 'undefined' && (window as any).rnDebug) {\n\t\t\tconst processed = args.map(arg => {\n\t\t\t\tif (arg instanceof Error && arg.stack) {\n\t\t\t\t\treturn `${arg.message}\\n${arg.stack}`;\n\t\t\t\t}\n\n\t\t\t\treturn arg;\n\t\t\t});\n\t\t\t(window as any).rnDebug(`${name} ${type}: ${processed.join(' ')}`);\n\t\t}\n\t};\n\n\treturn {\n\t\tlogState: process.env.NODE_ENV === 'test' ? E_SDK_LOG_LEVEL.SILENT : E_SDK_LOG_LEVEL.LOG,\n\n\t\tlog(...args: any[]) {\n\t\t\tif (this.logState <= E_SDK_LOG_LEVEL.LOG) {\n\t\t\t\tconsole.log(label, ...args);\n\t\t\t\trnDebug('log', args);\n\t\t\t}\n\t\t},\n\n\t\twarn(...args: any[]) {\n\t\t\tif (this.logState <= E_SDK_LOG_LEVEL.WARN) {\n\t\t\t\tconsole.warn(label, ...args);\n\t\t\t\trnDebug('warn', args);\n\t\t\t}\n\t\t},\n\n\t\terror(...args: any[]) {\n\t\t\tif (this.logState <= E_SDK_LOG_LEVEL.ERROR) {\n\t\t\t\tconsole.error(label, ...args);\n\n\t\t\t\trnDebug('error', args);\n\t\t\t}\n\t\t},\n\n\t\t// It's a bit tricky to prepend [MappedinJs] to assert and time because of how the output is structured in the console, so it is left out for simplicity\n\t\tassert(...args: any[]) {\n\t\t\tconsole.assert(...args);\n\t\t},\n\n\t\ttime(label: string) {\n\t\t\tconsole.time(label);\n\t\t},\n\n\t\ttimeEnd(label: string) {\n\t\t\tconsole.timeEnd(label);\n\t\t},\n\t\tsetLevel(level: E_SDK_LOG_LEVEL) {\n\t\t\tif (E_SDK_LOG_LEVEL.LOG <= level && level <= E_SDK_LOG_LEVEL.SILENT) {\n\t\t\t\tthis.logState = level;\n\t\t\t}\n\t\t},\n\t};\n}\n\nconst Logger = createLogger();\nexport function setLoggerLevel(level: E_SDK_LOG_LEVEL) {\n\tif (E_SDK_LOG_LEVEL.LOG <= level && level <= E_SDK_LOG_LEVEL.SILENT) {\n\t\tLogger.logState = level;\n\t}\n}\n\nexport default Logger;\n"],
5
+ "mappings": "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",
6
+ "names": ["useCallback", "useContext", "MappedinContext", "label", "useContext", "MappedinContext", "useCallback"]
7
+ }
@@ -0,0 +1,15 @@
1
+ import type { BaseExtensionState } from '@mappedin/react-native-sdk';
2
+ import type { BlueDotExtensionState } from './use-blue-dot';
3
+ /**
4
+ * Module augmentation to register the blue-dot extension type
5
+ * with the React Native SDK's extension registry.
6
+ *
7
+ * This allows TypeScript to properly type the extension state
8
+ * when accessed from the MappedinContext without type casting.
9
+ */
10
+ declare module '@mappedin/react-native-sdk' {
11
+ interface ExtensionRegistry {
12
+ 'blue-dot': BlueDotExtensionState & BaseExtensionState;
13
+ }
14
+ }
15
+ export {};
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Returns the extension registration script
3
+ * This function's return value is replaced at build time with the actual IIFE content
4
+ * @returns JavaScript code string for extension registration
5
+ */
6
+ export declare function getRegistrationScript(): string;
@@ -0,0 +1,40 @@
1
+ import type { BlueDotEvents, BlueDotEventPayloads } from '../types';
2
+ /**
3
+ * React hook for subscribing to BlueDot extension events in React Native WebView
4
+ *
5
+ * This hook provides a React-friendly way to listen for BlueDot events:
6
+ * - Automatically manages event subscription/unsubscription
7
+ * - Handles WebView bridge message routing
8
+ * - Provides type-safe event payload handling
9
+ * - Cleans up listeners on component unmount
10
+ *
11
+ * @param eventName - The name of the BlueDot event to listen for
12
+ * @param callback - The callback function to invoke when the event occurs
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * import { useBlueDotEvent } from '@mappedin/blue-dot/rn';
17
+ *
18
+ * function MyComponent() {
19
+ * // Listen for position updates
20
+ * useBlueDotEvent('position-update', (event) => {
21
+ * console.log('New position:', event.coordinate);
22
+ * console.log('Floor:', event.floor?.name);
23
+ * console.log('Accuracy:', event.accuracy);
24
+ * });
25
+ *
26
+ * // Listen for state changes
27
+ * useBlueDotEvent('state-change', (event) => {
28
+ * console.log('Blue Dot state changed to:', event.state);
29
+ * console.log('Action that caused change:', event.action);
30
+ * });
31
+ *
32
+ * // Listen for follow mode changes
33
+ * useBlueDotEvent('follow-change', (event) => {
34
+ * console.log('Following:', event.following);
35
+ * console.log('Mode:', event.mode);
36
+ * });
37
+ * }
38
+ * ```
39
+ */
40
+ export declare function useBlueDotEvent<K extends BlueDotEvents>(eventName: K, callback: (payload: BlueDotEventPayloads[K]) => void): void;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * React hook for registering the BlueDot extension with the WebView bridge
3
+ *
4
+ * This hook handles the complete extension registration lifecycle:
5
+ * - Monitors bridge readiness state
6
+ * - Checks if extension is already registered to avoid duplicates
7
+ * - Injects registration script when needed
8
+ * - Updates extension state in shared context
9
+ * - Handles all registration errors gracefully
10
+ *
11
+ * Multiple hooks can use this safely - the registration logic is idempotent
12
+ * and will only register the extension once per bridge lifecycle.
13
+ *
14
+ * @returns void - Hook performs registration as side effect only
15
+ */
16
+ export declare function useBlueDotRegistration(): void;
@@ -0,0 +1,131 @@
1
+ import type { BlueDotOptions, BlueDotPositionUpdate, BlueDotState, FollowMode, FollowCameraOptions } from '../types';
2
+ import type { Coordinate, Floor } from '@mappedin/mappedin-js';
3
+ /**
4
+ * Extension state for Blue Dot that includes the current state and position
5
+ */
6
+ export interface BlueDotExtensionState {
7
+ /**
8
+ * Whether the extension is currently enabled
9
+ */
10
+ isEnabled: boolean;
11
+ /**
12
+ * The current state of the Blue Dot
13
+ */
14
+ state: BlueDotState;
15
+ /**
16
+ * The current position of the Blue Dot
17
+ */
18
+ position?: Coordinate;
19
+ /**
20
+ * The current floor of the Blue Dot
21
+ */
22
+ floor?: Floor;
23
+ /**
24
+ * Whether the Blue Dot is currently following the user
25
+ */
26
+ following: boolean;
27
+ /**
28
+ * The accuracy of the current position in metres
29
+ */
30
+ accuracy?: number;
31
+ /**
32
+ * The direction the user is facing in degrees from north clockwise
33
+ */
34
+ heading?: number;
35
+ }
36
+ export interface UseBlueDotResult {
37
+ /**
38
+ * Whether the extension is ready and initialized
39
+ */
40
+ isReady: boolean;
41
+ /**
42
+ * Whether the extension is currently enabled
43
+ */
44
+ isEnabled: boolean;
45
+ /**
46
+ * The current state of the Blue Dot
47
+ */
48
+ state: BlueDotState;
49
+ /**
50
+ * The current position of the Blue Dot
51
+ */
52
+ position?: Coordinate;
53
+ /**
54
+ * The current floor of the Blue Dot
55
+ */
56
+ floor?: Floor;
57
+ /**
58
+ * Whether the Blue Dot is currently following the user
59
+ */
60
+ following: boolean;
61
+ /**
62
+ * The accuracy of the current position in metres
63
+ */
64
+ accuracy?: number;
65
+ /**
66
+ * The direction the user is facing in degrees from north clockwise
67
+ */
68
+ heading?: number;
69
+ /**
70
+ * Enables Blue Dot with the given options.
71
+ * @param options - The options to enable Blue Dot with
72
+ * @returns Promise that resolves when enabling is complete
73
+ * @see {@link BlueDot.enable}
74
+ */
75
+ enable(options?: BlueDotOptions): Promise<void>;
76
+ /**
77
+ * Disables the Blue Dot instance and unsubscribes all MapView event listeners.
78
+ * @returns Promise that resolves when disabling is complete
79
+ * @see {@link BlueDot.disable}
80
+ */
81
+ disable(): Promise<void>;
82
+ /**
83
+ * Update the Blue Dot's position manually.
84
+ * @param position - The position update options
85
+ * @returns Promise that resolves when the update is complete
86
+ * @see {@link BlueDot.update}
87
+ */
88
+ update(position: BlueDotPositionUpdate): Promise<void>;
89
+ /**
90
+ * Enable follow mode for the Blue Dot.
91
+ * @param mode - The follow mode to enable
92
+ * @param options - The follow camera options
93
+ * @returns Promise that resolves when follow mode is enabled
94
+ * @see {@link BlueDot.follow}
95
+ */
96
+ follow(mode: FollowMode, options?: FollowCameraOptions): Promise<void>;
97
+ /**
98
+ * Disable follow mode for the Blue Dot.
99
+ * @returns Promise that resolves when follow mode is disabled
100
+ * @see {@link BlueDot.unfollow}
101
+ */
102
+ unfollow(): Promise<void>;
103
+ }
104
+ /**
105
+ * React hook for using BlueDot extension in React Native WebView
106
+ *
107
+ * This hook provides an API for interacting with the BlueDot extension:
108
+ * - Uses the shared state system for automatic extension registration
109
+ * - Provides methods for controlling blue dot behavior
110
+ * - Handles bridge communication and error management
111
+ *
112
+ * @returns Hook API object with Blue Dot methods
113
+ *
114
+ * @example
115
+ * ```tsx
116
+ * import { MapView } from '@mappedin/react-native-sdk';
117
+ * import { useBlueDot } from '@mappedin/blue-dot/rn';
118
+ *
119
+ * function MyComponent() {
120
+ * const { enable, isReady, state, following } = useBlueDot();
121
+ *
122
+ * // Use the Blue Dot API
123
+ * React.useEffect(() => {
124
+ * if (isReady) {
125
+ * enable({ radius: 15, color: '#ff0000' });
126
+ * }
127
+ * }, [isReady]);
128
+ * }
129
+ * ```
130
+ */
131
+ export declare function useBlueDot(): UseBlueDotResult;