import type { Coordinate, Floor } from '@mappedin/mappedin-js'; import type z from 'zod'; import type { positionSchema } from './schemas'; import type { PartialDeep } from 'type-fest'; import { BlueDotAction, BlueDotStatus } from './status/types'; import { FollowMode } from './follow/types'; import type { PositionAnchor } from './fusion/types'; export type FollowCameraOptions = { /** * @default 21 */ zoomLevel?: number; /** * @default 45 */ pitch?: number; /** * Camera bearing in degrees clockwise from North. 0 is North, 90 is East, 180 is South, 270 is West. * This option is only available in 'position-only' mode. In all other modes, the bearing will be calculated automatically. * @default undefined */ bearing?: number; /** * @default undefined */ elevation?: number; /** * @default 1000 */ duration?: number; /** * @default 'ease-in-out' */ easing?: 'ease-in' | 'ease-out' | 'ease-in-out' | 'linear'; }; export type BlueDotEventPayloads = { /** * Emitted when the Blue Dot's position is updated either from the device's geolocation API or by calling {@link BlueDot.update}. * see {@link BlueDot.watchDevicePosition} for more details. */ 'position-update': { floor: Floor | undefined; heading: GeolocationPosition['coords']['heading'] | undefined; accuracy: GeolocationPosition['coords']['accuracy'] | undefined; coordinate: Coordinate; }; /** * Emitted when the device's orientation changes and the Blue Dot's heading is updated. * see {@link BlueDot.watchDeviceOrientation} for more details. */ 'device-orientation-update': { heading: GeolocationPosition['coords']['heading'] | undefined; }; /** * Emitted when the Blue Dot's status changes. */ 'status-change': { /** * The new status of the Blue Dot. */ status: BlueDotStatus; /** * The action that caused the status change. */ action: BlueDotAction; }; /** * Emitted when the Blue Dot encounters an error. */ error: GeolocationPositionError; /** * Emitted when the Blue Dot's following state changes. */ 'follow-change': { /** * Whether the Blue Dot is following the user. */ following: boolean; /** * The mode the Blue Dot is following the user in. */ mode?: FollowMode; }; /** * Emitted when the user clicks on the Blue Dot. */ click: { coordinate: Coordinate; }; /** * Emitted when the user hovers over the Blue Dot. */ hover: { coordinate: Coordinate; }; /** * Emitted when a calibration anchor is set (e.g. from VPS or {@link BlueDot.forcePosition}). */ 'anchor-set': { anchor: PositionAnchor; }; /** * Emitted when a calibration anchor's TTL expires. */ 'anchor-expired': { anchor: PositionAnchor; }; }; export type BlueDotEvents = keyof BlueDotEventPayloads; export type BlueDotState = { /** * Whether the BlueDot core element is visible. When false, the dot is hidden but the accuracy ring * and heading cone may still render based on their own visibility settings. * @default true */ visible: boolean; /** * The radius of the BlueDot in pixels. The BlueDot will maintain this size clamped to a minimum of 0.35 metres. * @default 10 */ radius: number; /** * The color of the BlueDot core element. * @default #2266ff */ color: string; /** * The color of the BlueDot when it has timed out and gone inactive. * @default #808080 */ inactiveColor: string; /** * Options for the accuracy ring around the BlueDot. */ accuracyRing: { /** * Whether the accuracy ring is visible. * @default true */ visible: boolean; /** * The color of the accuracy ring. * @default #2266ff */ color: string; /** * The opacity of the accuracy ring. * @default 0.3 */ opacity: number; }; /** * Options for the heading directional indicator. */ heading: { /** * Whether the heading cone is visible. * @default true */ visible: boolean; /** * The color of the heading cone. * @default #2266ff */ color: string; /** * The opacity of the heading cone. * @default 0.7 */ opacity: number; /** * Whether to display the heading cone when the BlueDot is inactive (timed out). * @default false */ displayWhenInactive: boolean; }; /** * The duration of the timeout in milliseconds. * If the BlueDot does not receive a position update within this time, it will grey out until a position is received. * @default 30000 */ timeout: number; /** * Whether to watch the device's position. * @default true */ watchDevicePosition: boolean; /** * Whether to log debug messages. * @default false */ debug: boolean; /** * The maximum acceptable accuracy in meters. Position updates with accuracy exceeding this value will be dropped. * @default 50 */ accuracyThreshold: number; /** * The initial state of the BlueDot when enabled. * @default 'hidden' */ initialState: 'hidden' | 'inactive'; /** * @hidden * Whether the BlueDot must remain within the map bounds. Disabling this will disable analytics as well. * @default true */ preventOutOfBounds: boolean; /** * If true, timestamp will be used to discard updates which are received out of order. * @default true */ discardStaleUpdates: boolean; }; export type BlueDotUpdateState = PartialDeep; /** * Position update options for the {@link BlueDot.update} method. */ export type BlueDotPositionUpdate = { /** * Latitude to override. * Set to `'device'` to reset to the device's latitude. */ latitude?: GeolocationPosition['coords']['latitude'] | 'device' | undefined; /** * Longitude to override. * Set to `'device'` to reset to the device's longitude. */ longitude?: GeolocationPosition['coords']['longitude'] | 'device' | undefined; /** * Accuracy to override. * Set to `'device'` to reset to the device's accuracy. * Set to `undefined` to disable the accuracy ring. */ accuracy?: GeolocationPosition['coords']['accuracy'] | 'device' | undefined; /** * Heading to override. * Set to `'device'` to reset to the device's heading. * Set to `undefined` to disable the heading indicator. */ heading?: GeolocationPosition['coords']['heading'] | 'device' | undefined; /** * Floor or floorId to override. * Set to `'device'` to reset to the device's floor level. * Set to `undefined` to disable floor level and show the BlueDot on all floors. */ floorOrFloorId?: Floor | string | 'device' | undefined; /** * Timestamp of the position update in milliseconds. */ timestamp?: number; }; export type BlueDotPositionUpdateWithFloor = Omit & { floor?: Floor | 'device' | undefined; }; export type ParsedBlueDotPosition = z.infer; export type BlueDotPositionProcessor = (current: BlueDotPositionUpdateWithFloor, incoming: BlueDotPositionUpdateWithFloor) => BlueDotPositionUpdateWithFloor | undefined; export type StateTransitions = { [Action in BlueDotAction]?: BlueDotStatus; }; export type StateMachine = { [State in BlueDotStatus]: { actions: StateTransitions; }; }; /** * Options for the BlueDot update method. */ export type BlueDotUpdateOptions = { /** * If true, maintains the current state and skips timers and analytics for this update. * @default false */ silent?: boolean; /** * If true, animates the position change. If false, updates immediately. * @default true */ animate?: boolean; }; export type GeolocationPositionExtended = GeolocationPosition & { coords: GeolocationPosition['coords'] & { readonly floorLevel?: number | null; }; };