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

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
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"]
4
+ "sourcesContent": ["import { MappedinContext } from '@mappedin/react-native-sdk';\nimport { useCallback, useContext, useRef } from 'react';\nimport type { BlueDot } from '../blue-dot';\nimport type { BlueDotUpdateState } from '../types';\nimport { useBlueDotEvent } from './use-blue-dot-events';\nimport { useBlueDotRegistration } from './use-blue-dot-registration';\nimport type { Asyncify, ConditionalExcept, ConditionalPick } from 'type-fest';\n\n/**\n * Extension state for Blue Dot that includes the current state and position\n */\nexport type BlueDotExtensionState = ConditionalExcept<BlueDot, (...args: any[]) => any>;\n\n/**\n * Helper type that asyncifies all methods from BlueDot, excluding event listener methods\n */\ntype AsyncBlueDotMethods = {\n\t[K in keyof Omit<ConditionalPick<BlueDot, (...args: any[]) => any>, 'on' | 'off'>]: Asyncify<BlueDot[K]>;\n};\n\n// Blue Dot hook return type\nexport interface UseBlueDotResult extends BlueDotExtensionState, Omit<AsyncBlueDotMethods, 'destroy'> {\n\t/**\n\t * Whether the extension is ready and initialized\n\t */\n\tisReady: boolean;\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?.status || 'hidden';\n\tconst following = extensionState?.isFollowing || false;\n\tconst position = extensionState?.coordinate;\n\tconst floor = extensionState?.floor;\n\tconst accuracy = extensionState?.accuracy;\n\tconst heading = extensionState?.heading;\n\tconst dotModel = extensionState?.dotModel;\n\tconst accuracyRingModel = extensionState?.accuracyRingModel;\n\tconst headingConeModel = extensionState?.headingConeModel;\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 status-change events to update state\n\tuseBlueDotEvent(\n\t\t'status-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\tstatus: event.status,\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\tisFollowing: 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?: BlueDotUpdateState): 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\tstatus: 'hidden',\n\t\t\tcoordinate: undefined,\n\t\t\tfloor: undefined,\n\t\t\tisFollowing: false,\n\t\t\taccuracy: undefined,\n\t\t\theading: undefined,\n\t\t});\n\t}, [callExtensionMethod, updateExtensionState]);\n\n\t// Create memoized wrappers for simple pass-through methods\n\tconst update = useCallback(\n\t\t(...args: Parameters<BlueDot['update']>) => callExtensionMethod('update', args),\n\t\t[callExtensionMethod],\n\t);\n\n\tconst follow = useCallback(\n\t\t(...args: Parameters<BlueDot['follow']>) => callExtensionMethod('follow', args),\n\t\t[callExtensionMethod],\n\t);\n\n\tconst getState = useCallback(\n\t\t(...args: Parameters<BlueDot['getState']>) => callExtensionMethod('getState', args),\n\t\t[callExtensionMethod],\n\t);\n\n\tconst updateState = useCallback(\n\t\t(...args: Parameters<BlueDot['updateState']>) => callExtensionMethod('updateState', args),\n\t\t[callExtensionMethod],\n\t);\n\n\tconst watchDevicePosition = useCallback(\n\t\t(...args: Parameters<BlueDot['watchDevicePosition']>) => callExtensionMethod('watchDevicePosition', args),\n\t\t[callExtensionMethod],\n\t);\n\n\tconst setPositionProcessor = useCallback(\n\t\t(...args: Parameters<BlueDot['setPositionProcessor']>) => callExtensionMethod('setPositionProcessor', args),\n\t\t[callExtensionMethod],\n\t);\n\n\t// Return hook API with Blue Dot methods\n\treturn {\n\t\tisReady,\n\t\tisEnabled,\n\t\tstatus: state,\n\t\tcoordinate: position,\n\t\tfloor,\n\t\tisFollowing: following,\n\t\taccuracy,\n\t\theading,\n\t\tdotModel,\n\t\taccuracyRingModel,\n\t\theadingConeModel,\n\t\tgetState,\n\t\tenable,\n\t\tdisable,\n\t\tupdate,\n\t\tupdateState,\n\t\tfollow,\n\t\twatchDevicePosition,\n\t\tsetPositionProcessor,\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": ["MappedinContext", "useCallback", "useContext", "label", "useContext", "MappedinContext", "useCallback"]
7
7
  }
@@ -0,0 +1,24 @@
1
+ import type { MapView, Model } from '@mappedin/mappedin-js';
2
+ import { Coordinate } from '@mappedin/mappedin-js';
3
+ import type { BlueDot } from './blue-dot';
4
+ import type { GeolocationPositionExtended, ParsedBlueDotPosition } from './types';
5
+ export declare class BlueDotModelManager {
6
+ #private;
7
+ dot?: Model;
8
+ accuracyRing?: Model;
9
+ headingCone?: Model;
10
+ constructor(mapView: MapView, BlueDot: BlueDot);
11
+ add(position: ParsedBlueDotPosition): void;
12
+ get options(): import("type-fest/source/readonly-deep").ReadonlyObjectDeep<import("./types").BlueDotState>;
13
+ getPosition(): Coordinate | undefined;
14
+ setPosition(value: Coordinate): void;
15
+ setAccuracy(value: GeolocationPositionExtended['coords']['accuracy'] | undefined): void;
16
+ setHeading(value: GeolocationPositionExtended['coords']['heading'] | undefined): void;
17
+ setAltitude(value: number | undefined): void;
18
+ /**
19
+ * Updates appearance of the BlueDot models based on a given status.
20
+ */
21
+ updateAppearance(): void;
22
+ remove(): void;
23
+ destroy(): void;
24
+ }
@@ -1,105 +1,20 @@
1
- import type { BlueDotOptions, BlueDotPositionUpdate, BlueDotState, FollowMode, FollowCameraOptions } from '../types';
2
- import type { Coordinate, Floor } from '@mappedin/mappedin-js';
1
+ import type { BlueDot } from '../blue-dot';
2
+ import type { Asyncify, ConditionalExcept, ConditionalPick } from 'type-fest';
3
3
  /**
4
4
  * Extension state for Blue Dot that includes the current state and position
5
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 {
6
+ export type BlueDotExtensionState = ConditionalExcept<BlueDot, (...args: any[]) => any>;
7
+ /**
8
+ * Helper type that asyncifies all methods from BlueDot, excluding event listener methods
9
+ */
10
+ type AsyncBlueDotMethods = {
11
+ [K in keyof Omit<ConditionalPick<BlueDot, (...args: any[]) => any>, 'on' | 'off'>]: Asyncify<BlueDot[K]>;
12
+ };
13
+ export interface UseBlueDotResult extends BlueDotExtensionState, Omit<AsyncBlueDotMethods, 'destroy'> {
37
14
  /**
38
15
  * Whether the extension is ready and initialized
39
16
  */
40
17
  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
18
  }
104
19
  /**
105
20
  * React hook for using BlueDot extension in React Native WebView
@@ -129,3 +44,4 @@ export interface UseBlueDotResult {
129
44
  * ```
130
45
  */
131
46
  export declare function useBlueDot(): UseBlueDotResult;
47
+ export {};
@@ -0,0 +1,22 @@
1
+ import z from 'zod';
2
+ export declare const geolocationPositionSchema: z.ZodObject<{
3
+ coords: z.ZodObject<{
4
+ latitude: z.ZodNumber;
5
+ longitude: z.ZodNumber;
6
+ accuracy: z.ZodNumber;
7
+ altitude: z.ZodNullable<z.ZodOptional<z.ZodNumber>>;
8
+ altitudeAccuracy: z.ZodNullable<z.ZodOptional<z.ZodNumber>>;
9
+ heading: z.ZodNullable<z.ZodOptional<z.ZodNumber>>;
10
+ speed: z.ZodNullable<z.ZodOptional<z.ZodNumber>>;
11
+ floorLevel: z.ZodNullable<z.ZodOptional<z.ZodNumber>>;
12
+ }, z.core.$strip>;
13
+ timestamp: z.ZodNumber;
14
+ }, z.core.$strip>;
15
+ export declare const positionSchema: z.ZodObject<{
16
+ latitude: z.ZodNumber;
17
+ longitude: z.ZodNumber;
18
+ floor: z.ZodOptional<z.ZodAny>;
19
+ accuracy: z.ZodOptional<z.ZodNumber>;
20
+ heading: z.ZodNullable<z.ZodOptional<z.ZodNumber>>;
21
+ timestamp: z.ZodOptional<z.ZodNumber>;
22
+ }, z.core.$strip>;
@@ -0,0 +1,2 @@
1
+ import type { StateMachine } from './types';
2
+ export declare const stateMachine: StateMachine;
package/lib/rn/types.d.ts CHANGED
@@ -1,5 +1,8 @@
1
1
  import type { Coordinate, Floor } from '@mappedin/mappedin-js';
2
+ import type z from 'zod';
2
3
  import type { EasingCurve } from '../../packages/common';
4
+ import type { positionSchema } from './schemas';
5
+ import type { PartialDeep } from 'type-fest';
3
6
  export type FollowMode =
4
7
  /** Camera position follows the Blue Dot's position. */
5
8
  'position-only'
@@ -48,15 +51,15 @@ export type BlueDotEventPayloads = {
48
51
  coordinate: Coordinate;
49
52
  };
50
53
  /**
51
- * Emitted when the Blue Dot's state changes.
54
+ * Emitted when the Blue Dot's status changes.
52
55
  */
53
- 'state-change': {
56
+ 'status-change': {
54
57
  /**
55
- * The new state of the Blue Dot.
58
+ * The new status of the Blue Dot.
56
59
  */
57
- state: BlueDotState;
60
+ status: BlueDotStatus;
58
61
  /**
59
- * The action that caused the state change.
62
+ * The action that caused the status change.
60
63
  */
61
64
  action: BlueDotAction;
62
65
  };
@@ -86,79 +89,98 @@ export type BlueDotEventPayloads = {
86
89
  /**
87
90
  * Emitted when the user hovers over the Blue Dot.
88
91
  */
89
- hover: undefined;
92
+ hover: {
93
+ coordinate: Coordinate;
94
+ };
90
95
  };
91
96
  export type BlueDotEvents = keyof BlueDotEventPayloads;
92
- export type BlueDotState = 'hidden' | 'active' | 'inactive' | 'disabled';
97
+ export type BlueDotStatus = 'hidden' | 'active' | 'inactive' | 'disabled';
93
98
  export type BlueDotAction = 'timeout' | 'error' | 'position-update' | 'enable' | 'disable' | 'initialize';
94
- export type BlueDotOptions = {
99
+ export type BlueDotState = {
95
100
  /**
96
101
  * The radius of the BlueDot in pixels. The BlueDot will maintain this size clamped to a minimum of 0.35 metres.
97
102
  * @default 10
98
103
  */
99
- radius?: number;
104
+ radius: number;
100
105
  /**
101
106
  * The color of the BlueDot core element.
102
107
  * @default #2266ff
103
108
  */
104
- color?: string;
109
+ color: string;
105
110
  /**
106
111
  * The color of the BlueDot when it has timed out and gone inactive.
107
112
  * @default #808080
108
113
  */
109
- inactiveColor?: string;
114
+ inactiveColor: string;
110
115
  /**
111
116
  * Options for the accuracy ring around the BlueDot.
112
117
  */
113
- accuracyRing?: {
118
+ accuracyRing: {
114
119
  /**
115
120
  * The color of the accuracy ring.
116
121
  * @default #2266ff
117
122
  */
118
- color?: string;
123
+ color: string;
119
124
  /**
120
125
  * The opacity of the accuracy ring.
121
126
  * @default 0.3
122
127
  */
123
- opacity?: number;
128
+ opacity: number;
124
129
  };
125
130
  /**
126
131
  * Options for the heading directional indicator.
127
132
  */
128
- heading?: {
133
+ heading: {
129
134
  /**
130
135
  * The color of the heading cone.
131
136
  * @default #2266ff
132
137
  */
133
- color?: string;
138
+ color: string;
134
139
  /**
135
140
  * The opacity of the heading cone.
136
141
  * @default 0.7
137
142
  */
138
- opacity?: number;
143
+ opacity: number;
144
+ /**
145
+ * Whether to display the heading cone when the BlueDot is inactive (timed out).
146
+ * @default false
147
+ */
148
+ displayWhenInactive: boolean;
139
149
  };
140
150
  /**
141
151
  * The duration of the timeout in milliseconds.
142
152
  * If the BlueDot does not receive a position update within this time, it will grey out until a position is received.
143
153
  * @default 30000
144
154
  */
145
- timeout?: number;
155
+ timeout: number;
146
156
  /**
147
157
  * Whether to watch the device's position.
148
158
  * @default true
149
159
  */
150
- watchDevicePosition?: boolean;
160
+ watchDevicePosition: boolean;
151
161
  /**
152
162
  * Whether to log debug messages.
153
163
  * @default false
154
164
  */
155
- debug?: boolean;
165
+ debug: boolean;
156
166
  /**
157
167
  * The maximum acceptable accuracy in meters. Position updates with accuracy exceeding this value will be dropped.
158
168
  * @default 50
159
169
  */
160
- accuracyThreshold?: number;
170
+ accuracyThreshold: number;
171
+ /**
172
+ * The initial state of the BlueDot when enabled.
173
+ * @default 'hidden'
174
+ */
175
+ initialState: 'hidden' | 'inactive';
176
+ /**
177
+ * @hidden
178
+ * Whether the BlueDot must remain within the map bounds. Disabling this will disable analytics as well.
179
+ * @default true
180
+ */
181
+ preventOutOfBounds: boolean;
161
182
  };
183
+ export type BlueDotUpdateState = PartialDeep<BlueDotState>;
162
184
  /**
163
185
  * Position update options for the {@link BlueDot.update} method.
164
186
  */
@@ -191,4 +213,41 @@ export type BlueDotPositionUpdate = {
191
213
  * Set to `undefined` to disable floor level and show the BlueDot on all floors.
192
214
  */
193
215
  floorOrFloorId?: Floor | string | 'device' | undefined;
216
+ /**
217
+ * Timestamp of the position update in milliseconds.
218
+ */
219
+ timestamp?: number;
220
+ };
221
+ export type BlueDotPositionUpdateWithFloor = Omit<BlueDotPositionUpdate, 'floorOrFloorId'> & {
222
+ floor?: Floor | 'device' | undefined;
223
+ };
224
+ export type ParsedBlueDotPosition = z.infer<typeof positionSchema>;
225
+ export type BlueDotPositionProcessor = (current: BlueDotPositionUpdateWithFloor, incoming: BlueDotPositionUpdateWithFloor) => BlueDotPositionUpdateWithFloor | undefined;
226
+ export type StateTransitions = {
227
+ [Action in BlueDotAction]?: BlueDotStatus;
228
+ };
229
+ export type StateMachine = {
230
+ [State in BlueDotStatus]: {
231
+ actions: StateTransitions;
232
+ };
233
+ };
234
+ /**
235
+ * Options for the BlueDot update method.
236
+ */
237
+ export type BlueDotUpdateOptions = {
238
+ /**
239
+ * If true, maintains the current state and skips timers and analytics for this update.
240
+ * @default false
241
+ */
242
+ silent?: boolean;
243
+ /**
244
+ * If true, animates the position change. If false, updates immediately.
245
+ * @default true
246
+ */
247
+ animate?: boolean;
248
+ };
249
+ export type GeolocationPositionExtended = GeolocationPosition & {
250
+ coords: GeolocationPosition['coords'] & {
251
+ readonly floorLevel?: number;
252
+ };
194
253
  };
@@ -0,0 +1,75 @@
1
+ import type { BlueDotPositionUpdateWithFloor, BlueDotState, BlueDotStatus, BlueDotUpdateState, GeolocationPositionExtended } from './types';
2
+ export declare function deepMergeState(existing: BlueDotState, update?: BlueDotUpdateState): BlueDotState;
3
+ /**
4
+ * Finds the intersection of a geographic line segment and a point.
5
+ *
6
+ * @param start - The start coordinate of the line segment.
7
+ * @param end - The end coordinate of the line segment.
8
+ * @param position - The position to check for intersection with the line segment.
9
+ */
10
+ export declare function getPointLineIntersection([startLongitude, startLatitude]: number[], [endLongitude, endLatitude]: number[], [positionLongitude, positionLatitude]: number[]): {
11
+ proportion: number;
12
+ intersection: [number, number];
13
+ distance: number;
14
+ } | undefined;
15
+ /**
16
+ * Finds the nearest segment of two coordinates on a path which the BlueDot position is closest to.
17
+ *
18
+ * @param pathCoordinates - The coordinates of the path to check.
19
+ * @param position - The position of the BlueDot.
20
+ */
21
+ export declare function findBlueDotOnPath(pathCoordinates: number[][], position: number[]): {
22
+ intersection: [number, number];
23
+ distance: number;
24
+ segmentIndex: number;
25
+ proportion: number;
26
+ } | undefined;
27
+ export declare function getPositionWithOverrides(update: BlueDotPositionUpdateWithFloor | undefined, overrides: BlueDotPositionUpdateWithFloor | undefined): BlueDotPositionUpdateWithFloor | undefined;
28
+ /**
29
+ * Compute whether a position is within circular pan bounds.
30
+ * @param positionLongitude The longitude to test
31
+ * @param positionLatitude The latitude to test
32
+ * @param radius The radius in meters
33
+ * @param center The center coordinate
34
+ * @returns True if within bounds, false otherwise
35
+ */
36
+ export declare function isWithinPanBounds({ longitude: positionLongitude, latitude: positionLatitude }: {
37
+ longitude: number;
38
+ latitude: number;
39
+ }, { radius, center }: {
40
+ radius: number;
41
+ center: {
42
+ longitude: number;
43
+ latitude: number;
44
+ };
45
+ }): boolean;
46
+ /**
47
+ * Compute BlueDot model scale from desired pixel radius and current meters-per-pixel.
48
+ * Ensures a minimum on-map size using MIN_BLUEDOT_RADIUS.
49
+ * @param radius Desired BlueDot radius in pixels
50
+ * @param metersPerPixel Current meters-per-pixel value
51
+ */
52
+ export declare function computeBlueDotScale(radius: number, metersPerPixel: number): number;
53
+ /**
54
+ * Ease-out cubic function used for smooth transitions.
55
+ * @example
56
+ * ```ts
57
+ * const eased = easeOutCubic(0.5);
58
+ * ```
59
+ */
60
+ export declare function easeOutCubic(t: number): number;
61
+ /**
62
+ * Interpolate altitude between a start altitude and target altitude using time-based easing.
63
+ * @param now Current timestamp (ms)
64
+ * @param startTime Transition start timestamp (ms)
65
+ * @param duration Transition duration (ms)
66
+ * @param startAltitude Altitude at the start of the transition
67
+ * @param targetAltitude Current target altitude to reach
68
+ * @returns The interpolated altitude and completion flag
69
+ */
70
+ export declare function interpolateAltitude(now: number, startTime: number | undefined, duration: number, startAltitude: number | undefined, targetAltitude: number): {
71
+ altitude: number;
72
+ done: boolean;
73
+ };
74
+ export declare function shouldShowHeadingCone(state: BlueDotStatus, heading: GeolocationPositionExtended['coords']['heading'] | undefined, displayWhenInactive: boolean): boolean;
75
+ export declare function shouldShowAccuracyRing(state: BlueDotStatus, accuracy: GeolocationPositionExtended['coords']['accuracy'] | undefined): boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mappedin/blue-dot",
3
- "version": "6.0.1-beta.57",
3
+ "version": "6.0.1-beta.58",
4
4
  "homepage": "https://developer.mappedin.com/",
5
5
  "private": false,
6
6
  "main": "lib/esm/index.js",
@@ -9,14 +9,19 @@
9
9
  "types": "lib/esm/index.d.ts",
10
10
  "exports": {
11
11
  ".": {
12
+ "types": "./lib/esm/index.d.ts",
12
13
  "import": "./lib/esm/index.js",
13
- "require": "./lib/esm/index.js",
14
- "types": "./lib/esm/index.d.ts"
14
+ "require": "./lib/esm/index.js"
15
15
  },
16
16
  "./rn": {
17
+ "types": "./lib/rn/index-rn.d.ts",
17
18
  "import": "./lib/rn/index-rn.js",
18
- "require": "./lib/rn/index-rn.js",
19
- "types": "./lib/rn/index-rn.d.ts"
19
+ "require": "./lib/rn/index-rn.js"
20
+ },
21
+ "./react": {
22
+ "types": "./lib/esm/react/index.d.ts",
23
+ "import": "./lib/esm/react/index.js",
24
+ "require": "./lib/esm/react/index.js"
20
25
  }
21
26
  },
22
27
  "typesVersions": {
@@ -36,13 +41,17 @@
36
41
  "dependencies": {},
37
42
  "peerDependencies": {
38
43
  "react": ">=16.8.0",
39
- "@mappedin/mappedin-js": "^6.0.0-rc.4",
40
- "@mappedin/react-native-sdk": "^6.0.0-beta.1"
44
+ "@mappedin/mappedin-js": "^6.1.0",
45
+ "@mappedin/react-sdk": "^6.1.0",
46
+ "@mappedin/react-native-sdk": "^6.1.0"
41
47
  },
42
48
  "peerDependenciesMeta": {
43
49
  "@mappedin/react-native-sdk": {
44
50
  "optional": true
45
51
  },
52
+ "@mappedin/react-sdk": {
53
+ "optional": true
54
+ },
46
55
  "react": {
47
56
  "optional": true
48
57
  }