@mappedin/blue-dot 6.0.1-beta.61 → 6.5.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,867 +1,1256 @@
1
- // Generated by dts-bundle v0.7.3
2
- // Dependencies for this module:
3
- // ../blue-dot/@mappedin/mappedin-js
4
- // ../blue-dot/@packages/internal/common/extensions
5
- // ../blue-dot/@packages/internal/common/pubsub
6
- // ../blue-dot/type-fest
7
- // ../blue-dot/zod
8
- // ../blue-dot/three
9
-
10
- declare module '@mappedin/blue-dot' {
11
- export { BlueDot } from '@mappedin/blue-dot/blue-dot/src/blue-dot';
12
- export type { BlueDotEvents, BlueDotEventPayloads, BlueDotPositionUpdate, BlueDotStatus, BlueDotAction, FollowMode, FollowCameraOptions, BlueDotState, BlueDotPositionProcessor, BlueDotPositionUpdateWithFloor, BlueDotUpdateOptions, GeolocationPositionExtended, } from '@mappedin/blue-dot/blue-dot/src/types';
13
- }
1
+ import { Coordinate, Floor, MapView, Model } from "@mappedin/mappedin-js";
14
2
 
15
- declare module '@mappedin/blue-dot/blue-dot/src/blue-dot' {
16
- import type { Floor, MapView, Model } from '@mappedin/mappedin-js';
17
- import { Coordinate } from '@mappedin/mappedin-js';
18
- import type { MapViewExtension } from '@packages/internal/common/extensions';
19
- import { PubSub } from '@packages/internal/common/pubsub';
20
- import type { BlueDotEventPayloads, BlueDotState, BlueDotPositionProcessor, BlueDotPositionUpdate, BlueDotStatus, BlueDotUpdateOptions, FollowCameraOptions, FollowMode, GeolocationPositionExtended, BlueDotUpdateState } from '@mappedin/blue-dot/blue-dot/src/types';
21
- import type { ReadonlyDeep } from 'type-fest';
22
- /**
23
- * Show a Blue Dot indicating the device's position on the map.
24
- *
25
- * @example
26
- * ```ts
27
- * import { show3dMap } from '@mappedin/mappedin-js';
28
- * import { BlueDot } from '@mappedin/blue-dot';
29
- *
30
- * const mapView = await show3dMap(...);
31
- *
32
- * // Enable BlueDot
33
- * new BlueDot(mapView).enable();
34
- *
35
- * // Option 1: Listen for position updates from the device
36
- * mapView.BlueDot.on('position-update', (position) => {
37
- * console.log('User position:', position);
38
- * });
39
- *
40
- * // Option 2: Update position manually
41
- * new BlueDot(mapView).update({ latitude, longitude, accuracy, floorOrFloorId });
42
- *
43
- * ```
44
- */
45
- export class BlueDot implements MapViewExtension<BlueDotState> {
46
- #private;
47
- /**
48
- * Create a new {@link BlueDot} instance.
49
- */
50
- constructor(mapView: MapView);
51
- /**
52
- * Get the Model for the BlueDot core element.
53
- */
54
- get dotModel(): Model | undefined;
55
- /**
56
- * Get the Model for the accuracy ring.
57
- */
58
- get accuracyRingModel(): Model | undefined;
59
- /**
60
- * Get the Model for the heading cone.
61
- */
62
- get headingConeModel(): Model | undefined;
63
- /**
64
- * Whether the BlueDot is currently enabled.
65
- */
66
- get isEnabled(): boolean;
67
- /**
68
- * The current state of the BlueDot. Can be 'hidden', 'active', 'inactive', or 'disabled'.
69
- * Listen for state changes using the 'status-change' event.
70
- *
71
- * @example
72
- * mapView.BlueDot.on('status-change', ({ status }) => {
73
- * if (status === 'active') {
74
- * // BlueDot is visible and tracking
75
- * }
76
- * });
77
- */
78
- get status(): BlueDotStatus;
79
- /**
80
- * Whether the BlueDot is currently following the user (camera follow mode).
81
- */
82
- get isFollowing(): boolean;
83
- /**
84
- * The direction the user is facing in degrees from north clockwise.
85
- * @see https://developer.mozilla.org/en-US/docs/Web/API/GeolocationCoordinates/heading
86
- */
87
- get heading(): GeolocationPosition['coords']['heading'] | undefined;
88
- /**
89
- * The accuracy of the current position in metres.
90
- */
91
- get accuracy(): GeolocationPosition['coords']['accuracy'] | undefined;
92
- /**
93
- * The coordinate of the current position.
94
- */
95
- get coordinate(): Coordinate | undefined;
96
- getState: () => ReadonlyDeep<BlueDotState>;
97
- /**
98
- * The floor the Blue Dot is currently on. If undefined, the Blue Dot will appear on every floor.
99
- */
100
- get floor(): Floor | undefined;
101
- /**
102
- * Enable the Blue Dot. It will be hidden until a position is received either from the browser or by calling {@link BlueDot.update}.
103
- * @param options - The options to setup the Blue Dot (see {@link BlueDotOptions}).
104
- *
105
- * @example Enable with default options
106
- * mapView.BlueDot.enable();
107
- *
108
- * @example Enable with custom color and accuracy ring
109
- * mapView.BlueDot.enable({ color: '#00ff00', accuracyRing: { color: '#00ff00', opacity: 0.2 } });
110
- *
111
- * @see See the [BlueDot Guide](https://developer.mappedin.com/web-sdk/blue-dot) for more information.
112
- */
113
- enable: (options?: BlueDotUpdateState) => void;
114
- /**
115
- * Disable the Blue Dot. It will be hidden and no longer update.
116
- */
117
- disable: () => void;
118
- /**
119
- * Subscribe to a BlueDot event.
120
- * @param eventName The name of the event to listen for.
121
- * @param fn The function to call when the event is emitted.
122
- */
123
- on: PubSub<BlueDotEventPayloads>['on'];
124
- /**
125
- * Unsubscribe from a BlueDot event.
126
- * @param eventName The name of the event to unsubscribe from.
127
- * @param fn The function to unsubscribe from the event.
128
- */
129
- off: PubSub<BlueDotEventPayloads>['off'];
130
- /**
131
- * Update the BlueDot state after it has been enabled.
132
- * This allows overriding previously set values like colors, and other options.
133
- * @param options - The options to update
134
- *
135
- * @example Update color and accuracy ring
136
- * mapView.BlueDot.updateState({
137
- * color: '#ff0000',
138
- * accuracyRing: { color: '#ff0000', opacity: 0.5 }
139
- * });
140
- */
141
- updateState: (options: BlueDotUpdateState) => void;
142
- /**
143
- * Enable or disable the devices's geolocation listener to automatically position the Blue Dot.
144
- * If enabled, the device will request permission to access the user's precise location.
145
- * @param watch - Whether to enable or disable the listener.
146
- */
147
- watchDevicePosition: (watch: boolean) => void;
148
- /**
149
- * Manually override some position properties of the Blue Dot.
150
- * Accepts a full GeolocationPosition object or a partial {@link BlueDotPositionUpdate} object.
151
- * @example Manually set the accuracy and heading
152
- * ```ts
153
- * api.BlueDot.update({ accuracy: 10, heading: 90 });
154
- * ```
155
- * @example Reset accuracy and heading to device values
156
- * ```ts
157
- * api.BlueDot.update({ accuracy: 'device', heading: 'device' });
158
- * ```
159
- */
160
- update: (position: GeolocationPositionExtended | BlueDotPositionUpdate | undefined, options?: BlueDotUpdateOptions) => void;
161
- /**
162
- * Set the camera to follow the BlueDot in various modes. User interaction will cancel following automatically.
163
- * @param mode The follow mode ('position-only', 'position-and-heading', 'position-and-path-direction', or false to disable).
164
- * @param cameraOptions Optional camera options (zoom, pitch, etc.).
165
- *
166
- * @example
167
- * mapView.BlueDot.follow('position-and-heading', { zoomLevel: 21, pitch: 45 });
168
- */
169
- follow: (mode: FollowMode, cameraOptions?: FollowCameraOptions) => void;
170
- /**
171
- * Set a position processor callback that allows intercepting and modifying device/geolocation position updates before they are applied.
172
- *
173
- * **Note**: This processor only applies to automatic position updates from device geolocation.
174
- * Manual position updates via `update()` method bypass the processor and are applied directly.
175
- *
176
- * @param processor - A callback function that receives current state and incoming update. Return undefined to discard the update, or return a modified update object.
177
- *
178
- * @example Discard inaccurate positions
179
- * ```ts
180
- * blueDot.setPositionProcessor((current, incoming) => {
181
- * if (incoming.accuracy && incoming.accuracy > 50) {
182
- * return undefined; // Discard update
183
- * }
184
- * return incoming; // Accept update
185
- * });
186
- * ```
187
- *
188
- * @example Modify incoming positions
189
- * ```ts
190
- * blueDot.setPositionProcessor((current, incoming) => {
191
- * // Apply custom smoothing or validation logic
192
- * return {
193
- * ...incoming,
194
- * accuracy: Math.min(incoming.accuracy || 100, 10) // Cap accuracy
195
- * };
196
- * });
197
- * ```
198
- */
199
- setPositionProcessor(processor?: BlueDotPositionProcessor): void;
200
- destroy: () => void;
201
- }
202
- }
3
+ //#region ../../node_modules/.pnpm/type-fest@4.41.0/node_modules/type-fest/source/primitive.d.ts
203
4
 
204
- declare module '@mappedin/blue-dot/blue-dot/src/types' {
205
- import type { Coordinate, Floor } from '@mappedin/mappedin-js';
206
- import type z from 'zod';
207
- import type { EasingCurve } from '@mappedin/blue-dot/packages/common';
208
- import type { positionSchema } from '@mappedin/blue-dot/blue-dot/src/schemas';
209
- import type { PartialDeep } from 'type-fest';
210
- export type FollowMode =
211
- /** Camera position follows the Blue Dot's position. */
212
- 'position-only'
213
- /** Camera position follows the Blue Dot's position. Camera bearing matches the Blue Dot's heading. */
214
- | 'position-and-heading'
215
- /** Camera position follows the Blue Dot's position. Camera bearing is calculated based on the Navigation path. */
216
- | 'position-and-path-direction'
217
- /** Disables follow mode */
218
- | false;
219
- export type FollowCameraOptions = {
220
- /**
221
- * @default 21
222
- */
223
- zoomLevel?: number;
224
- /**
225
- * @default 45
226
- */
227
- pitch?: number;
228
- /**
229
- * Camera bearing in degrees clockwise from North. 0 is North, 90 is East, 180 is South, 270 is West.
230
- * This option is only available in 'position-only' mode. In all other modes, the bearing will be calculated automatically.
231
- * @default undefined
232
- */
233
- bearing?: number;
234
- /**
235
- * @default undefined
236
- */
237
- elevation?: number;
238
- /**
239
- * @default 1000
240
- */
241
- duration?: number;
242
- /**
243
- * @default 'ease-in-out'
244
- */
245
- easing?: EasingCurve;
246
- };
247
- export type BlueDotEventPayloads = {
248
- /**
249
- * Emitted when the Blue Dot's position is updated.
250
- */
251
- 'position-update': {
252
- floor: Floor | undefined;
253
- heading: GeolocationPosition['coords']['heading'] | undefined;
254
- accuracy: GeolocationPosition['coords']['accuracy'] | undefined;
255
- coordinate: Coordinate;
256
- };
257
- /**
258
- * Emitted when the Blue Dot's status changes.
259
- */
260
- 'status-change': {
261
- /**
262
- * The new status of the Blue Dot.
263
- */
264
- status: BlueDotStatus;
265
- /**
266
- * The action that caused the status change.
267
- */
268
- action: BlueDotAction;
269
- };
270
- /**
271
- * Emitted when the Blue Dot encounters an error.
272
- */
273
- error: GeolocationPositionError;
274
- /**
275
- * Emitted when the Blue Dot's following state changes.
276
- */
277
- 'follow-change': {
278
- /**
279
- * Whether the Blue Dot is following the user.
280
- */
281
- following: boolean;
282
- /**
283
- * The mode the Blue Dot is following the user in.
284
- */
285
- mode?: FollowMode;
286
- };
287
- /**
288
- * Emitted when the user clicks on the Blue Dot.
289
- */
290
- click: {
291
- coordinate: Coordinate;
292
- };
293
- /**
294
- * Emitted when the user hovers over the Blue Dot.
295
- */
296
- hover: {
297
- coordinate: Coordinate;
298
- };
299
- };
300
- export type BlueDotEvents = keyof BlueDotEventPayloads;
301
- export type BlueDotStatus = 'hidden' | 'active' | 'inactive' | 'disabled';
302
- export type BlueDotAction = 'timeout' | 'error' | 'position-update' | 'enable' | 'disable' | 'initialize';
303
- export type BlueDotState = {
304
- /**
305
- * The radius of the BlueDot in pixels. The BlueDot will maintain this size clamped to a minimum of 0.35 metres.
306
- * @default 10
307
- */
308
- radius: number;
309
- /**
310
- * The color of the BlueDot core element.
311
- * @default #2266ff
312
- */
313
- color: string;
314
- /**
315
- * The color of the BlueDot when it has timed out and gone inactive.
316
- * @default #808080
317
- */
318
- inactiveColor: string;
319
- /**
320
- * Options for the accuracy ring around the BlueDot.
321
- */
322
- accuracyRing: {
323
- /**
324
- * The color of the accuracy ring.
325
- * @default #2266ff
326
- */
327
- color: string;
328
- /**
329
- * The opacity of the accuracy ring.
330
- * @default 0.3
331
- */
332
- opacity: number;
333
- };
334
- /**
335
- * Options for the heading directional indicator.
336
- */
337
- heading: {
338
- /**
339
- * The color of the heading cone.
340
- * @default #2266ff
341
- */
342
- color: string;
343
- /**
344
- * The opacity of the heading cone.
345
- * @default 0.7
346
- */
347
- opacity: number;
348
- /**
349
- * Whether to display the heading cone when the BlueDot is inactive (timed out).
350
- * @default false
351
- */
352
- displayWhenInactive: boolean;
353
- };
354
- /**
355
- * The duration of the timeout in milliseconds.
356
- * If the BlueDot does not receive a position update within this time, it will grey out until a position is received.
357
- * @default 30000
358
- */
359
- timeout: number;
360
- /**
361
- * Whether to watch the device's position.
362
- * @default true
363
- */
364
- watchDevicePosition: boolean;
365
- /**
366
- * Whether to log debug messages.
367
- * @default false
368
- */
369
- debug: boolean;
370
- /**
371
- * The maximum acceptable accuracy in meters. Position updates with accuracy exceeding this value will be dropped.
372
- * @default 50
373
- */
374
- accuracyThreshold: number;
375
- /**
376
- * The initial state of the BlueDot when enabled.
377
- * @default 'hidden'
378
- */
379
- initialState: 'hidden' | 'inactive';
380
- /**
381
- * @hidden
382
- * Whether the BlueDot must remain within the map bounds. Disabling this will disable analytics as well.
383
- * @default true
384
- */
385
- preventOutOfBounds: boolean;
386
- };
387
- export type BlueDotUpdateState = PartialDeep<BlueDotState>;
388
- /**
389
- * Position update options for the {@link BlueDot.update} method.
390
- */
391
- export type BlueDotPositionUpdate = {
392
- /**
393
- * Latitude to override.
394
- * Set to `'device'` to reset to the device's latitude.
395
- */
396
- latitude?: GeolocationPosition['coords']['latitude'] | 'device' | undefined;
397
- /**
398
- * Longitude to override.
399
- * Set to `'device'` to reset to the device's longitude.
400
- */
401
- longitude?: GeolocationPosition['coords']['longitude'] | 'device' | undefined;
402
- /**
403
- * Accuracy to override.
404
- * Set to `'device'` to reset to the device's accuracy.
405
- * Set to `undefined` to disable the accuracy ring.
406
- */
407
- accuracy?: GeolocationPosition['coords']['accuracy'] | 'device' | undefined;
408
- /**
409
- * Heading to override.
410
- * Set to `'device'` to reset to the device's heading.
411
- * Set to `undefined` to disable the heading indicator.
412
- */
413
- heading?: GeolocationPosition['coords']['heading'] | 'device' | undefined;
414
- /**
415
- * Floor or floorId to override.
416
- * Set to `'device'` to reset to the device's floor level.
417
- * Set to `undefined` to disable floor level and show the BlueDot on all floors.
418
- */
419
- floorOrFloorId?: Floor | string | 'device' | undefined;
420
- /**
421
- * Timestamp of the position update in milliseconds.
422
- */
423
- timestamp?: number;
424
- };
425
- export type BlueDotPositionUpdateWithFloor = Omit<BlueDotPositionUpdate, 'floorOrFloorId'> & {
426
- floor?: Floor | 'device' | undefined;
427
- };
428
- export type ParsedBlueDotPosition = z.infer<typeof positionSchema>;
429
- export type BlueDotPositionProcessor = (current: BlueDotPositionUpdateWithFloor, incoming: BlueDotPositionUpdateWithFloor) => BlueDotPositionUpdateWithFloor | undefined;
430
- export type StateTransitions = {
431
- [Action in BlueDotAction]?: BlueDotStatus;
432
- };
433
- export type StateMachine = {
434
- [State in BlueDotStatus]: {
435
- actions: StateTransitions;
436
- };
437
- };
438
- /**
439
- * Options for the BlueDot update method.
440
- */
441
- export type BlueDotUpdateOptions = {
442
- /**
443
- * If true, maintains the current state and skips timers and analytics for this update.
444
- * @default false
445
- */
446
- silent?: boolean;
447
- /**
448
- * If true, animates the position change. If false, updates immediately.
449
- * @default true
450
- */
451
- animate?: boolean;
452
- };
453
- export type GeolocationPositionExtended = GeolocationPosition & {
454
- coords: GeolocationPosition['coords'] & {
455
- readonly floorLevel?: number;
456
- };
457
- };
5
+ /**
6
+ Matches any [primitive value](https://developer.mozilla.org/en-US/docs/Glossary/Primitive).
7
+
8
+ @category Type
9
+ */
10
+ type Primitive = null | undefined | string | number | boolean | symbol | bigint;
11
+ //#endregion
12
+ //#region ../../node_modules/.pnpm/type-fest@4.41.0/node_modules/type-fest/source/observable-like.d.ts
13
+ declare global {
14
+ // eslint-disable-next-line @typescript-eslint/consistent-type-definitions -- It has to be an `interface` so that it can be merged.
15
+ interface SymbolConstructor {
16
+ readonly observable: symbol;
17
+ }
458
18
  }
459
19
 
460
- declare module '@mappedin/blue-dot/packages/common' {
461
- import Logger from '@mappedin/blue-dot/packages/common/Mappedin.Logger';
462
- export * from '@mappedin/blue-dot/packages/common/errors';
463
- export * from '@mappedin/blue-dot/packages/common/utils';
464
- export * from '@mappedin/blue-dot/packages/common/async';
465
- export * from '@mappedin/blue-dot/packages/common/assert';
466
- export * from '@mappedin/blue-dot/packages/common/random-id';
467
- export { PubSub } from '@mappedin/blue-dot/packages/common/pubsub';
468
- export { SafeStorage, SESSION_ID_KEY, DEVICE_ID_KEY } from '@mappedin/blue-dot/packages/common/storage';
469
- export { Logger };
470
- export * from '@mappedin/blue-dot/packages/common/color';
471
- export * from '@mappedin/blue-dot/packages/common/interpolate';
20
+ /**
21
+ @remarks
22
+ The TC39 observable proposal defines a `closed` property, but some implementations (such as xstream) do not as of 10/08/2021.
23
+ As well, some guidance on making an `Observable` to not include `closed` property.
24
+ @see https://github.com/tc39/proposal-observable/blob/master/src/Observable.js#L129-L130
25
+ @see https://github.com/staltz/xstream/blob/6c22580c1d84d69773ee4b0905df44ad464955b3/src/index.ts#L79-L85
26
+ @see https://github.com/benlesh/symbol-observable#making-an-object-observable
27
+
28
+ @category Observable
29
+ */
30
+
31
+ //#endregion
32
+ //#region ../../node_modules/.pnpm/type-fest@4.41.0/node_modules/type-fest/source/optional-keys-of.d.ts
33
+ /**
34
+ Extract all optional keys from the given type.
35
+
36
+ This is useful when you want to create a new type that contains different type values for the optional keys only.
37
+
38
+ @example
39
+ ```
40
+ import type {OptionalKeysOf, Except} from 'type-fest';
41
+
42
+ interface User {
43
+ name: string;
44
+ surname: string;
45
+
46
+ luckyNumber?: number;
472
47
  }
473
48
 
474
- declare module '@mappedin/blue-dot/blue-dot/src/schemas' {
475
- import z from 'zod';
476
- export const geolocationPositionSchema: z.ZodObject<{
477
- coords: z.ZodObject<{
478
- latitude: z.ZodNumber;
479
- longitude: z.ZodNumber;
480
- accuracy: z.ZodNumber;
481
- altitude: z.ZodNullable<z.ZodOptional<z.ZodNumber>>;
482
- altitudeAccuracy: z.ZodNullable<z.ZodOptional<z.ZodNumber>>;
483
- heading: z.ZodNullable<z.ZodOptional<z.ZodNumber>>;
484
- speed: z.ZodNullable<z.ZodOptional<z.ZodNumber>>;
485
- floorLevel: z.ZodNullable<z.ZodOptional<z.ZodNumber>>;
486
- }, z.core.$strip>;
487
- timestamp: z.ZodNumber;
488
- }, z.core.$strip>;
489
- export const positionSchema: z.ZodObject<{
490
- latitude: z.ZodNumber;
491
- longitude: z.ZodNumber;
492
- floor: z.ZodOptional<z.ZodAny>;
493
- accuracy: z.ZodOptional<z.ZodNumber>;
494
- heading: z.ZodNullable<z.ZodOptional<z.ZodNumber>>;
495
- timestamp: z.ZodOptional<z.ZodNumber>;
496
- }, z.core.$strip>;
49
+ const REMOVE_FIELD = Symbol('remove field symbol');
50
+ type UpdateOperation<Entity extends object> = Except<Partial<Entity>, OptionalKeysOf<Entity>> & {
51
+ [Key in OptionalKeysOf<Entity>]?: Entity[Key] | typeof REMOVE_FIELD;
52
+ };
53
+
54
+ const update1: UpdateOperation<User> = {
55
+ name: 'Alice'
56
+ };
57
+
58
+ const update2: UpdateOperation<User> = {
59
+ name: 'Bob',
60
+ luckyNumber: REMOVE_FIELD
61
+ };
62
+ ```
63
+
64
+ @category Utilities
65
+ */
66
+ type OptionalKeysOf<BaseType extends object> = BaseType extends unknown // For distributing `BaseType`
67
+ ? (keyof { [Key in keyof BaseType as BaseType extends Record<Key, BaseType[Key]> ? never : Key]: never }) & (keyof BaseType) // Intersect with `keyof BaseType` to ensure result of `OptionalKeysOf<BaseType>` is always assignable to `keyof BaseType`
68
+ : never;
69
+ //#endregion
70
+ //#region ../../node_modules/.pnpm/type-fest@4.41.0/node_modules/type-fest/source/required-keys-of.d.ts
71
+ /**
72
+ Extract all required keys from the given type.
73
+
74
+ This is useful when you want to create a new type that contains different type values for the required keys only or use the list of keys for validation purposes, etc...
75
+
76
+ @example
77
+ ```
78
+ import type {RequiredKeysOf} from 'type-fest';
79
+
80
+ declare function createValidation<Entity extends object, Key extends RequiredKeysOf<Entity> = RequiredKeysOf<Entity>>(field: Key, validator: (value: Entity[Key]) => boolean): ValidatorFn;
81
+
82
+ interface User {
83
+ name: string;
84
+ surname: string;
85
+
86
+ luckyNumber?: number;
497
87
  }
498
88
 
499
- declare module '@mappedin/blue-dot/packages/common/Mappedin.Logger' {
500
- export const MI_DEBUG_KEY = "mi-debug";
501
- export const MI_ERROR_LABEL = "[MappedinJS]";
502
- export enum E_SDK_LOG_LEVEL {
503
- LOG = 0,
504
- WARN = 1,
505
- ERROR = 2,
506
- SILENT = 3
507
- }
508
- export function createLogger(name?: string, { prefix }?: {
509
- prefix?: string | undefined;
510
- }): {
511
- logState: E_SDK_LOG_LEVEL;
512
- log(...args: any[]): void;
513
- warn(...args: any[]): void;
514
- error(...args: any[]): void;
515
- assert(...args: any[]): void;
516
- time(label: string): void;
517
- timeEnd(label: string): void;
518
- setLevel(level: E_SDK_LOG_LEVEL): void;
519
- };
520
- const Logger: {
521
- logState: E_SDK_LOG_LEVEL;
522
- log(...args: any[]): void;
523
- warn(...args: any[]): void;
524
- error(...args: any[]): void;
525
- assert(...args: any[]): void;
526
- time(label: string): void;
527
- timeEnd(label: string): void;
528
- setLevel(level: E_SDK_LOG_LEVEL): void;
529
- };
530
- export function setLoggerLevel(level: E_SDK_LOG_LEVEL): void;
531
- export default Logger;
89
+ const validator1 = createValidation<User>('name', value => value.length < 25);
90
+ const validator2 = createValidation<User>('surname', value => value.length < 25);
91
+ ```
92
+
93
+ @category Utilities
94
+ */
95
+ type RequiredKeysOf<BaseType extends object> = BaseType extends unknown // For distributing `BaseType`
96
+ ? Exclude<keyof BaseType, OptionalKeysOf<BaseType>> : never;
97
+ //#endregion
98
+ //#region ../../node_modules/.pnpm/type-fest@4.41.0/node_modules/type-fest/source/is-never.d.ts
99
+ /**
100
+ Returns a boolean for whether the given type is `never`.
101
+
102
+ @link https://github.com/microsoft/TypeScript/issues/31751#issuecomment-498526919
103
+ @link https://stackoverflow.com/a/53984913/10292952
104
+ @link https://www.zhenghao.io/posts/ts-never
105
+
106
+ Useful in type utilities, such as checking if something does not occur.
107
+
108
+ @example
109
+ ```
110
+ import type {IsNever, And} from 'type-fest';
111
+
112
+ // https://github.com/andnp/SimplyTyped/blob/master/src/types/strings.ts
113
+ type AreStringsEqual<A extends string, B extends string> =
114
+ And<
115
+ IsNever<Exclude<A, B>> extends true ? true : false,
116
+ IsNever<Exclude<B, A>> extends true ? true : false
117
+ >;
118
+
119
+ type EndIfEqual<I extends string, O extends string> =
120
+ AreStringsEqual<I, O> extends true
121
+ ? never
122
+ : void;
123
+
124
+ function endIfEqual<I extends string, O extends string>(input: I, output: O): EndIfEqual<I, O> {
125
+ if (input === output) {
126
+ process.exit(0);
127
+ }
532
128
  }
533
129
 
534
- declare module '@mappedin/blue-dot/packages/common/errors' {
535
- /**
536
- * @internal
537
- */
538
- export class MappedinError extends Error {
539
- constructor(message: string, label?: string);
540
- }
541
- /**
542
- * @internal
543
- */
544
- export class MappedinRenderError extends MappedinError {
545
- constructor(message: string, label?: string);
546
- }
130
+ endIfEqual('abc', 'abc');
131
+ //=> never
132
+
133
+ endIfEqual('abc', '123');
134
+ //=> void
135
+ ```
136
+
137
+ @category Type Guard
138
+ @category Utilities
139
+ */
140
+ type IsNever<T> = [T] extends [never] ? true : false;
141
+ //#endregion
142
+ //#region ../../node_modules/.pnpm/type-fest@4.41.0/node_modules/type-fest/source/if-never.d.ts
143
+ /**
144
+ An if-else-like type that resolves depending on whether the given type is `never`.
145
+
146
+ @see {@link IsNever}
147
+
148
+ @example
149
+ ```
150
+ import type {IfNever} from 'type-fest';
151
+
152
+ type ShouldBeTrue = IfNever<never>;
153
+ //=> true
154
+
155
+ type ShouldBeBar = IfNever<'not never', 'foo', 'bar'>;
156
+ //=> 'bar'
157
+ ```
158
+
159
+ @category Type Guard
160
+ @category Utilities
161
+ */
162
+ type IfNever<T, TypeIfNever = true, TypeIfNotNever = false> = (IsNever<T> extends true ? TypeIfNever : TypeIfNotNever);
163
+ //#endregion
164
+ //#region ../../node_modules/.pnpm/type-fest@4.41.0/node_modules/type-fest/source/is-any.d.ts
165
+ // Can eventually be replaced with the built-in once this library supports
166
+ // TS5.4+ only. Tracked in https://github.com/sindresorhus/type-fest/issues/848
167
+ type NoInfer<T> = T extends infer U ? U : never;
168
+
169
+ /**
170
+ Returns a boolean for whether the given type is `any`.
171
+
172
+ @link https://stackoverflow.com/a/49928360/1490091
173
+
174
+ Useful in type utilities, such as disallowing `any`s to be passed to a function.
175
+
176
+ @example
177
+ ```
178
+ import type {IsAny} from 'type-fest';
179
+
180
+ const typedObject = {a: 1, b: 2} as const;
181
+ const anyObject: any = {a: 1, b: 2};
182
+
183
+ function get<O extends (IsAny<O> extends true ? {} : Record<string, number>), K extends keyof O = keyof O>(obj: O, key: K) {
184
+ return obj[key];
547
185
  }
548
186
 
549
- declare module '@mappedin/blue-dot/packages/common/utils' {
550
- import { Box2 } from 'three';
551
- import type { Box3 } from 'three';
552
- export function findMapWithElevationClosestToZero<T extends {
553
- elevation?: number;
554
- }>(maps: T[]): T | undefined;
555
- /**
556
- * Omit properites from object
557
- */
558
- export function omit<T extends Record<string, any>, K extends keyof T>(obj: T, keysToOmit: K[]): Omit<T, K>;
559
- export function decodeAccessToken(accessToken: string): {
560
- sub: string;
561
- aud: string[];
562
- capabilities: Record<string, any>;
563
- };
564
- export function toRadians(degrees: number): number;
565
- export function toDegrees(radians: number): number;
566
- export function round(value: number, decimals: number): number;
567
- export function euclideanModulo(value: number, modulus: number): number;
568
- /**
569
- * Position from our SDKs may be tuple of longitude and latitude optionally followed by altitude.
570
- */
571
- type Position = [number, number] | [number, number, number?] | number[];
572
- /**
573
- * Calculates the approximate distance between two geographic coordinates on Earth's surface.
574
- *
575
- * This function uses the equirectangular approximation method to compute the distance, which simplifies
576
- * the math and speeds up calculations, but is less accurate over long distances compared to other methods
577
- * like the haversine formula.
578
- *
579
- * @param point1 - The first point's longitude and latitude as [longitude, latitude].
580
- * @param point1 - The second point's longitude and latitude as [longitude, latitude].
581
- * @return The approximate distance between the two points in meters.
582
- */
583
- export function haversineDistance([lon1, lat1]: Position, [lon2, lat2]: Position): number;
584
- /**
585
- * Calculates the bearing clockwise from North between two geographic coordinates on Earth's surface.
586
- * 0 is North, 90 is East, 180 is South, 270 is West.
587
- *
588
- * @param point1 - The first point's longitude and latitude as [longitude, latitude].
589
- * @param point2 - The second point's longitude and latitude as [longitude, latitude].
590
- * @returns The forward bearing in degrees from point1 to point2, measured clockwise from true North.
591
- */
592
- export function getForwardBearing([lon1, lat1]: Position, [lon2, lat2]: Position): number;
593
- /**
594
- *
595
- * Normalizes the start and end rotations to the range 0 to 2 PI and ensures the shortest path for rotation.
596
- *
597
- * @param startRotation - The start rotation in radians
598
- * @param targetRotation - The target rotation in radians
599
- * @returns Start and end rotations for the tween.
600
- */
601
- export function shortestTweenRotation(startRotation: number, targetRotation: number): {
602
- start: number;
603
- end: number;
604
- };
605
- export function isFiniteBox(box: Box2 | Box3): boolean;
606
- export { clampWithWarning } from '@mappedin/blue-dot/packages/common/math-utils';
607
- export { arraysEqual } from '@mappedin/blue-dot/packages/common/array-utils';
608
- export function isBrowser(): boolean;
609
- /**
610
- * Calculates the simple Euclidean distance between two geographic coordinates.
611
- *
612
- * This treats longitude and latitude as Cartesian coordinates on a flat plane.
613
- * It's the fastest distance calculation but least accurate for geographic data.
614
- * Best used for relative distance comparisons rather than actual measurements.
615
- *
616
- * @param point1 - The first point's longitude and latitude as [longitude, latitude].
617
- * @param point2 - The second point's longitude and latitude as [longitude, latitude].
618
- * @returns The Euclidean distance between the two points in meters.
619
- */
620
- export function euclideanDistance(point1: Position, point2: Position): number;
621
- /**
622
- * Calculates the approximate distance between two geographic coordinates on Earth's surface.
623
- *
624
- * This function uses the equirectangular approximation method to compute the distance, which simplifies
625
- * the math and speeds up calculations, but is less accurate over long distances compared to other methods
626
- * like the haversine formula.
627
- *
628
- * @param point1 - The first point's longitude and latitude as [longitude, latitude].
629
- * @param point2 - The second point's longitude and latitude as [longitude, latitude].
630
- * @returns The approximate distance between the two points in meters.
631
- */
632
- export function equirectangularDistance(point1: Position, point2: Position): number;
187
+ const typedA = get(typedObject, 'a');
188
+ //=> 1
189
+
190
+ const anyA = get(anyObject, 'a');
191
+ //=> any
192
+ ```
193
+
194
+ @category Type Guard
195
+ @category Utilities
196
+ */
197
+ type IsAny<T> = 0 extends 1 & NoInfer<T> ? true : false;
198
+ //#endregion
199
+ //#region ../../node_modules/.pnpm/type-fest@4.41.0/node_modules/type-fest/source/simplify.d.ts
200
+ /**
201
+ Useful to flatten the type output to improve type hints shown in editors. And also to transform an interface into a type to aide with assignability.
202
+
203
+ @example
204
+ ```
205
+ import type {Simplify} from 'type-fest';
206
+
207
+ type PositionProps = {
208
+ top: number;
209
+ left: number;
210
+ };
211
+
212
+ type SizeProps = {
213
+ width: number;
214
+ height: number;
215
+ };
216
+
217
+ // In your editor, hovering over `Props` will show a flattened object with all the properties.
218
+ type Props = Simplify<PositionProps & SizeProps>;
219
+ ```
220
+
221
+ Sometimes it is desired to pass a value as a function argument that has a different type. At first inspection it may seem assignable, and then you discover it is not because the `value`'s type definition was defined as an interface. In the following example, `fn` requires an argument of type `Record<string, unknown>`. If the value is defined as a literal, then it is assignable. And if the `value` is defined as type using the `Simplify` utility the value is assignable. But if the `value` is defined as an interface, it is not assignable because the interface is not sealed and elsewhere a non-string property could be added to the interface.
222
+
223
+ If the type definition must be an interface (perhaps it was defined in a third-party npm package), then the `value` can be defined as `const value: Simplify<SomeInterface> = ...`. Then `value` will be assignable to the `fn` argument. Or the `value` can be cast as `Simplify<SomeInterface>` if you can't re-declare the `value`.
224
+
225
+ @example
226
+ ```
227
+ import type {Simplify} from 'type-fest';
228
+
229
+ interface SomeInterface {
230
+ foo: number;
231
+ bar?: string;
232
+ baz: number | undefined;
633
233
  }
634
234
 
635
- declare module '@mappedin/blue-dot/packages/common/async' {
636
- export function debounce<T extends (...args: any[]) => void>(func: T, wait: number, immediate?: boolean): (...args: Parameters<T>) => void;
235
+ type SomeType = {
236
+ foo: number;
237
+ bar?: string;
238
+ baz: number | undefined;
239
+ };
240
+
241
+ const literal = {foo: 123, bar: 'hello', baz: 456};
242
+ const someType: SomeType = literal;
243
+ const someInterface: SomeInterface = literal;
244
+
245
+ function fn(object: Record<string, unknown>): void {}
246
+
247
+ fn(literal); // Good: literal object type is sealed
248
+ fn(someType); // Good: type is sealed
249
+ fn(someInterface); // Error: Index signature for type 'string' is missing in type 'someInterface'. Because `interface` can be re-opened
250
+ fn(someInterface as Simplify<SomeInterface>); // Good: transform an `interface` into a `type`
251
+ ```
252
+
253
+ @link https://github.com/microsoft/TypeScript/issues/15300
254
+ @see SimplifyDeep
255
+ @category Object
256
+ */
257
+ type Simplify<T> = { [KeyType in keyof T]: T[KeyType] } & {};
258
+ //#endregion
259
+ //#region ../../node_modules/.pnpm/type-fest@4.41.0/node_modules/type-fest/source/omit-index-signature.d.ts
260
+ /**
261
+ Omit any index signatures from the given object type, leaving only explicitly defined properties.
262
+
263
+ This is the counterpart of `PickIndexSignature`.
264
+
265
+ Use-cases:
266
+ - Remove overly permissive signatures from third-party types.
267
+
268
+ This type was taken from this [StackOverflow answer](https://stackoverflow.com/a/68261113/420747).
269
+
270
+ It relies on the fact that an empty object (`{}`) is assignable to an object with just an index signature, like `Record<string, unknown>`, but not to an object with explicitly defined keys, like `Record<'foo' | 'bar', unknown>`.
271
+
272
+ (The actual value type, `unknown`, is irrelevant and could be any type. Only the key type matters.)
273
+
274
+ ```
275
+ const indexed: Record<string, unknown> = {}; // Allowed
276
+
277
+ const keyed: Record<'foo', unknown> = {}; // Error
278
+ // => TS2739: Type '{}' is missing the following properties from type 'Record<"foo" | "bar", unknown>': foo, bar
279
+ ```
280
+
281
+ Instead of causing a type error like the above, you can also use a [conditional type](https://www.typescriptlang.org/docs/handbook/2/conditional-types.html) to test whether a type is assignable to another:
282
+
283
+ ```
284
+ type Indexed = {} extends Record<string, unknown>
285
+ ? '✅ `{}` is assignable to `Record<string, unknown>`'
286
+ : '❌ `{}` is NOT assignable to `Record<string, unknown>`';
287
+ // => '✅ `{}` is assignable to `Record<string, unknown>`'
288
+
289
+ type Keyed = {} extends Record<'foo' | 'bar', unknown>
290
+ ? "✅ `{}` is assignable to `Record<'foo' | 'bar', unknown>`"
291
+ : "❌ `{}` is NOT assignable to `Record<'foo' | 'bar', unknown>`";
292
+ // => "❌ `{}` is NOT assignable to `Record<'foo' | 'bar', unknown>`"
293
+ ```
294
+
295
+ Using a [mapped type](https://www.typescriptlang.org/docs/handbook/2/mapped-types.html#further-exploration), you can then check for each `KeyType` of `ObjectType`...
296
+
297
+ ```
298
+ import type {OmitIndexSignature} from 'type-fest';
299
+
300
+ type OmitIndexSignature<ObjectType> = {
301
+ [KeyType in keyof ObjectType // Map each key of `ObjectType`...
302
+ ]: ObjectType[KeyType]; // ...to its original value, i.e. `OmitIndexSignature<Foo> == Foo`.
303
+ };
304
+ ```
305
+
306
+ ...whether an empty object (`{}`) would be assignable to an object with that `KeyType` (`Record<KeyType, unknown>`)...
307
+
308
+ ```
309
+ import type {OmitIndexSignature} from 'type-fest';
310
+
311
+ type OmitIndexSignature<ObjectType> = {
312
+ [KeyType in keyof ObjectType
313
+ // Is `{}` assignable to `Record<KeyType, unknown>`?
314
+ as {} extends Record<KeyType, unknown>
315
+ ? ... // ✅ `{}` is assignable to `Record<KeyType, unknown>`
316
+ : ... // ❌ `{}` is NOT assignable to `Record<KeyType, unknown>`
317
+ ]: ObjectType[KeyType];
318
+ };
319
+ ```
320
+
321
+ If `{}` is assignable, it means that `KeyType` is an index signature and we want to remove it. If it is not assignable, `KeyType` is a "real" key and we want to keep it.
322
+
323
+ @example
324
+ ```
325
+ import type {OmitIndexSignature} from 'type-fest';
326
+
327
+ interface Example {
328
+ // These index signatures will be removed.
329
+ [x: string]: any
330
+ [x: number]: any
331
+ [x: symbol]: any
332
+ [x: `head-${string}`]: string
333
+ [x: `${string}-tail`]: string
334
+ [x: `head-${string}-tail`]: string
335
+ [x: `${bigint}`]: string
336
+ [x: `embedded-${number}`]: string
337
+
338
+ // These explicitly defined keys will remain.
339
+ foo: 'bar';
340
+ qux?: 'baz';
637
341
  }
638
342
 
639
- declare module '@mappedin/blue-dot/packages/common/assert' {
640
- /**
641
- * Options for assertExists function
642
- */
643
- export interface AssertExistsOptions {
644
- /** Name of the value being checked (for better error messages) */
645
- valueName?: string;
646
- /** Custom error message to use instead of the default */
647
- customMessage?: string;
648
- /** Error class to use (defaults to AssertionError) */
649
- errorClass?: new (message: string) => Error;
650
- /** Whether to capture and format the stack trace (defaults to true) */
651
- captureStackTrace?: boolean;
652
- }
653
- /**
654
- * Custom error class for assertions to make stack traces more identifiable
655
- */
656
- export class AssertionError extends Error {
657
- name: string;
658
- constructor(message: string);
659
- }
660
- /**
661
- * Asserts that a value is not null or undefined.
662
- * @param value The value to check
663
- * @param options Optional configuration for the assertion
664
- */
665
- export function assertExists<T>(value: T, options?: AssertExistsOptions): asserts value is NonNullable<T>;
666
- /**
667
- * Asserts that an object is an instance of a specific class.
668
- * @param obj The object to check
669
- * @param className The class constructor to check against
670
- * @param errorMessage Optional custom error message
671
- */
672
- export function assertInstanceOf<T>(obj: unknown, className: new (...args: any[]) => T, errorMessage?: string): asserts obj is T;
673
- /**
674
- * Asserts that an object has a specific 'type' property value.
675
- * @param obj The object to check
676
- * @param expectedType The expected value of the 'type' property
677
- * @param errorMessage Optional custom error message
678
- */
679
- export function assertType<T extends {
680
- type: string;
681
- }, P extends T['type']>(obj: T | undefined, expectedType: P, errorMessage?: string): asserts obj is Extract<T, {
682
- type: P;
683
- }>;
684
- /**
685
- * Retrieves an entity from a map and asserts it is of a specific type.
686
- * @param map The map containing entities
687
- * @param entityId The ID of the entity to retrieve
688
- * @param expectedType The class constructor the entity should be an instance of
689
- * @returns The entity cast to the expected type
690
- */
691
- export function getEntityAsType<T>(map: Map<string | number, unknown>, entityId: string | number, expectedType: new (...args: any[]) => T): T;
343
+ type ExampleWithoutIndexSignatures = OmitIndexSignature<Example>;
344
+ // => { foo: 'bar'; qux?: 'baz' | undefined; }
345
+ ```
346
+
347
+ @see PickIndexSignature
348
+ @category Object
349
+ */
350
+ type OmitIndexSignature<ObjectType> = { [KeyType in keyof ObjectType as {} extends Record<KeyType, unknown> ? never : KeyType]: ObjectType[KeyType] };
351
+ //#endregion
352
+ //#region ../../node_modules/.pnpm/type-fest@4.41.0/node_modules/type-fest/source/pick-index-signature.d.ts
353
+ /**
354
+ Pick only index signatures from the given object type, leaving out all explicitly defined properties.
355
+
356
+ This is the counterpart of `OmitIndexSignature`.
357
+
358
+ @example
359
+ ```
360
+ import type {PickIndexSignature} from 'type-fest';
361
+
362
+ declare const symbolKey: unique symbol;
363
+
364
+ type Example = {
365
+ // These index signatures will remain.
366
+ [x: string]: unknown;
367
+ [x: number]: unknown;
368
+ [x: symbol]: unknown;
369
+ [x: `head-${string}`]: string;
370
+ [x: `${string}-tail`]: string;
371
+ [x: `head-${string}-tail`]: string;
372
+ [x: `${bigint}`]: string;
373
+ [x: `embedded-${number}`]: string;
374
+
375
+ // These explicitly defined keys will be removed.
376
+ ['kebab-case-key']: string;
377
+ [symbolKey]: string;
378
+ foo: 'bar';
379
+ qux?: 'baz';
380
+ };
381
+
382
+ type ExampleIndexSignature = PickIndexSignature<Example>;
383
+ // {
384
+ // [x: string]: unknown;
385
+ // [x: number]: unknown;
386
+ // [x: symbol]: unknown;
387
+ // [x: `head-${string}`]: string;
388
+ // [x: `${string}-tail`]: string;
389
+ // [x: `head-${string}-tail`]: string;
390
+ // [x: `${bigint}`]: string;
391
+ // [x: `embedded-${number}`]: string;
392
+ // }
393
+ ```
394
+
395
+ @see OmitIndexSignature
396
+ @category Object
397
+ */
398
+ type PickIndexSignature<ObjectType> = { [KeyType in keyof ObjectType as {} extends Record<KeyType, unknown> ? KeyType : never]: ObjectType[KeyType] };
399
+ //#endregion
400
+ //#region ../../node_modules/.pnpm/type-fest@4.41.0/node_modules/type-fest/source/merge.d.ts
401
+ // Merges two objects without worrying about index signatures.
402
+ type SimpleMerge<Destination, Source> = { [Key in keyof Destination as Key extends keyof Source ? never : Key]: Destination[Key] } & Source;
403
+
404
+ /**
405
+ Merge two types into a new type. Keys of the second type overrides keys of the first type.
406
+
407
+ @example
408
+ ```
409
+ import type {Merge} from 'type-fest';
410
+
411
+ interface Foo {
412
+ [x: string]: unknown;
413
+ [x: number]: unknown;
414
+ foo: string;
415
+ bar: symbol;
692
416
  }
693
417
 
694
- declare module '@mappedin/blue-dot/packages/common/random-id' {
695
- /**
696
- * Returns a UUIDv4-like ID without relying on a CSPRNG as we don't need it for these purposes.
697
- * @hidden
698
- */
699
- export const randomId: () => string;
700
- export function cyrb53(str: string, seed?: number): number;
701
- export function shortId(): string;
418
+ type Bar = {
419
+ [x: number]: number;
420
+ [x: symbol]: unknown;
421
+ bar: Date;
422
+ baz: boolean;
423
+ };
424
+
425
+ export type FooBar = Merge<Foo, Bar>;
426
+ // => {
427
+ // [x: string]: unknown;
428
+ // [x: number]: number;
429
+ // [x: symbol]: unknown;
430
+ // foo: string;
431
+ // bar: Date;
432
+ // baz: boolean;
433
+ // }
434
+ ```
435
+
436
+ @category Object
437
+ */
438
+ type Merge<Destination, Source> = Simplify<SimpleMerge<PickIndexSignature<Destination>, PickIndexSignature<Source>> & SimpleMerge<OmitIndexSignature<Destination>, OmitIndexSignature<Source>>>;
439
+ //#endregion
440
+ //#region ../../node_modules/.pnpm/type-fest@4.41.0/node_modules/type-fest/source/if-any.d.ts
441
+ /**
442
+ An if-else-like type that resolves depending on whether the given type is `any`.
443
+
444
+ @see {@link IsAny}
445
+
446
+ @example
447
+ ```
448
+ import type {IfAny} from 'type-fest';
449
+
450
+ type ShouldBeTrue = IfAny<any>;
451
+ //=> true
452
+
453
+ type ShouldBeBar = IfAny<'not any', 'foo', 'bar'>;
454
+ //=> 'bar'
455
+ ```
456
+
457
+ @category Type Guard
458
+ @category Utilities
459
+ */
460
+ type IfAny<T, TypeIfAny = true, TypeIfNotAny = false> = (IsAny<T> extends true ? TypeIfAny : TypeIfNotAny);
461
+ //#endregion
462
+ //#region ../../node_modules/.pnpm/type-fest@4.41.0/node_modules/type-fest/source/internal/type.d.ts
463
+ /**
464
+ Matches any primitive, `void`, `Date`, or `RegExp` value.
465
+ */
466
+ type BuiltIns = Primitive | void | Date | RegExp;
467
+ /**
468
+ Test if the given function has multiple call signatures.
469
+
470
+ Needed to handle the case of a single call signature with properties.
471
+
472
+ Multiple call signatures cannot currently be supported due to a TypeScript limitation.
473
+ @see https://github.com/microsoft/TypeScript/issues/29732
474
+ */
475
+ type HasMultipleCallSignatures<T extends (...arguments_: any[]) => unknown> = T extends {
476
+ (...arguments_: infer A): unknown;
477
+ (...arguments_: infer B): unknown;
478
+ } ? B extends A ? A extends B ? false : true : true : false;
479
+ //#endregion
480
+ //#region ../../node_modules/.pnpm/type-fest@4.41.0/node_modules/type-fest/source/internal/object.d.ts
481
+
482
+ /**
483
+ Merges user specified options with default options.
484
+
485
+ @example
486
+ ```
487
+ type PathsOptions = {maxRecursionDepth?: number; leavesOnly?: boolean};
488
+ type DefaultPathsOptions = {maxRecursionDepth: 10; leavesOnly: false};
489
+ type SpecifiedOptions = {leavesOnly: true};
490
+
491
+ type Result = ApplyDefaultOptions<PathsOptions, DefaultPathsOptions, SpecifiedOptions>;
492
+ //=> {maxRecursionDepth: 10; leavesOnly: true}
493
+ ```
494
+
495
+ @example
496
+ ```
497
+ // Complains if default values are not provided for optional options
498
+
499
+ type PathsOptions = {maxRecursionDepth?: number; leavesOnly?: boolean};
500
+ type DefaultPathsOptions = {maxRecursionDepth: 10};
501
+ type SpecifiedOptions = {};
502
+
503
+ type Result = ApplyDefaultOptions<PathsOptions, DefaultPathsOptions, SpecifiedOptions>;
504
+ // ~~~~~~~~~~~~~~~~~~~
505
+ // Property 'leavesOnly' is missing in type 'DefaultPathsOptions' but required in type '{ maxRecursionDepth: number; leavesOnly: boolean; }'.
506
+ ```
507
+
508
+ @example
509
+ ```
510
+ // Complains if an option's default type does not conform to the expected type
511
+
512
+ type PathsOptions = {maxRecursionDepth?: number; leavesOnly?: boolean};
513
+ type DefaultPathsOptions = {maxRecursionDepth: 10; leavesOnly: 'no'};
514
+ type SpecifiedOptions = {};
515
+
516
+ type Result = ApplyDefaultOptions<PathsOptions, DefaultPathsOptions, SpecifiedOptions>;
517
+ // ~~~~~~~~~~~~~~~~~~~
518
+ // Types of property 'leavesOnly' are incompatible. Type 'string' is not assignable to type 'boolean'.
519
+ ```
520
+
521
+ @example
522
+ ```
523
+ // Complains if an option's specified type does not conform to the expected type
524
+
525
+ type PathsOptions = {maxRecursionDepth?: number; leavesOnly?: boolean};
526
+ type DefaultPathsOptions = {maxRecursionDepth: 10; leavesOnly: false};
527
+ type SpecifiedOptions = {leavesOnly: 'yes'};
528
+
529
+ type Result = ApplyDefaultOptions<PathsOptions, DefaultPathsOptions, SpecifiedOptions>;
530
+ // ~~~~~~~~~~~~~~~~
531
+ // Types of property 'leavesOnly' are incompatible. Type 'string' is not assignable to type 'boolean'.
532
+ ```
533
+ */
534
+ type ApplyDefaultOptions<Options extends object, Defaults extends Simplify<Omit<Required<Options>, RequiredKeysOf<Options>> & Partial<Record<RequiredKeysOf<Options>, never>>>, SpecifiedOptions extends Options> = IfAny<SpecifiedOptions, Defaults, IfNever<SpecifiedOptions, Defaults, Simplify<Merge<Defaults, { [Key in keyof SpecifiedOptions as Key extends OptionalKeysOf<Options> ? Extract<SpecifiedOptions[Key], undefined> extends never ? Key : never : Key]: SpecifiedOptions[Key] }> & Required<Options>> // `& Required<Options>` ensures that `ApplyDefaultOptions<SomeOption, ...>` is always assignable to `Required<SomeOption>`
535
+ >>;
536
+ //#endregion
537
+ //#region ../../node_modules/.pnpm/type-fest@4.41.0/node_modules/type-fest/source/partial-deep.d.ts
538
+ /**
539
+ @see {@link PartialDeep}
540
+ */
541
+ type PartialDeepOptions = {
542
+ /**
543
+ Whether to affect the individual elements of arrays and tuples.
544
+ @default false
545
+ */
546
+ readonly recurseIntoArrays?: boolean;
547
+
548
+ /**
549
+ Allows `undefined` values in non-tuple arrays.
550
+ - When set to `true`, elements of non-tuple arrays can be `undefined`.
551
+ - When set to `false`, only explicitly defined elements are allowed in non-tuple arrays, ensuring stricter type checking.
552
+ @default true
553
+ @example
554
+ You can prevent `undefined` values in non-tuple arrays by passing `{recurseIntoArrays: true; allowUndefinedInNonTupleArrays: false}` as the second type argument:
555
+ ```
556
+ import type {PartialDeep} from 'type-fest';
557
+ type Settings = {
558
+ languages: string[];
559
+ };
560
+ declare const partialSettings: PartialDeep<Settings, {recurseIntoArrays: true; allowUndefinedInNonTupleArrays: false}>;
561
+ partialSettings.languages = [undefined]; // Error
562
+ partialSettings.languages = []; // Ok
563
+ ```
564
+ */
565
+ readonly allowUndefinedInNonTupleArrays?: boolean;
566
+ };
567
+ type DefaultPartialDeepOptions = {
568
+ recurseIntoArrays: false;
569
+ allowUndefinedInNonTupleArrays: true;
570
+ };
571
+
572
+ /**
573
+ Create a type from another type with all keys and nested keys set to optional.
574
+
575
+ Use-cases:
576
+ - Merging a default settings/config object with another object, the second object would be a deep partial of the default object.
577
+ - Mocking and testing complex entities, where populating an entire object with its keys would be redundant in terms of the mock or test.
578
+
579
+ @example
580
+ ```
581
+ import type {PartialDeep} from 'type-fest';
582
+
583
+ const settings: Settings = {
584
+ textEditor: {
585
+ fontSize: 14,
586
+ fontColor: '#000000',
587
+ fontWeight: 400
588
+ },
589
+ autocomplete: false,
590
+ autosave: true
591
+ };
592
+
593
+ const applySavedSettings = (savedSettings: PartialDeep<Settings>) => {
594
+ return {...settings, ...savedSettings};
702
595
  }
703
596
 
704
- declare module '@mappedin/blue-dot/packages/common/pubsub' {
705
- /**
706
- * Generic PubSub class implementing the Publish-Subscribe pattern for event handling.
707
- *
708
- * @template EVENT_PAYLOAD - The type of the event payload.
709
- * @template EVENT - The type of the event.
710
- */
711
- export class PubSub<EVENT_PAYLOAD, EVENT extends keyof EVENT_PAYLOAD = keyof EVENT_PAYLOAD> {
712
- /**
713
- * @private
714
- * @internal
715
- */
716
- publish<EVENT_NAME extends EVENT>(eventName: EVENT_NAME, data?: EVENT_PAYLOAD[EVENT_NAME]): void;
717
- /**
718
- * Subscribe a function to an event.
719
- *
720
- * @param eventName An event name which, when fired, will call the provided
721
- * function.
722
- * @param fn A callback that gets called when the corresponding event is fired. The
723
- * callback will get passed an argument with a type that's one of event payloads.
724
- * @example
725
- * // Subscribe to the 'click' event
726
- * const handler = (event) => {
727
- * const { coordinate } = event;
728
- * const { latitude, longitude } = coordinate;
729
- * console.log(`Map was clicked at ${latitude}, ${longitude}`);
730
- * };
731
- * map.on('click', handler);
732
- */
733
- on<EVENT_NAME extends EVENT>(eventName: EVENT_NAME, fn: (payload: EVENT_PAYLOAD[EVENT_NAME] extends {
734
- data: null;
735
- } ? EVENT_PAYLOAD[EVENT_NAME]['data'] : EVENT_PAYLOAD[EVENT_NAME]) => void): void;
736
- /**
737
- * Unsubscribe a function previously subscribed with {@link on}
738
- *
739
- * @param eventName An event name to which the provided function was previously
740
- * subscribed.
741
- * @param fn A function that was previously passed to {@link on}. The function must
742
- * have the same reference as the function that was subscribed.
743
- * @example
744
- * // Unsubscribe from the 'click' event
745
- * const handler = (event) => {
746
- * console.log('Map was clicked', event);
747
- * };
748
- * map.off('click', handler);
749
- */
750
- off<EVENT_NAME extends EVENT>(eventName: EVENT_NAME, fn: (payload: EVENT_PAYLOAD[EVENT_NAME] extends {
751
- data: null;
752
- } ? EVENT_PAYLOAD[EVENT_NAME]['data'] : EVENT_PAYLOAD[EVENT_NAME]) => void): void;
753
- /**
754
- * @private
755
- * @internal
756
- */
757
- destroy(): void;
758
- }
597
+ settings = applySavedSettings({textEditor: {fontWeight: 500}});
598
+ ```
599
+
600
+ By default, this does not affect elements in array and tuple types. You can change this by passing `{recurseIntoArrays: true}` as the second type argument:
601
+
602
+ ```
603
+ import type {PartialDeep} from 'type-fest';
604
+
605
+ type Settings = {
606
+ languages: string[];
759
607
  }
760
608
 
761
- declare module '@mappedin/blue-dot/packages/common/storage' {
762
- export const SESSION_DATA_KEY: "mi-session-data";
763
- export const LOCAL_DATA_KEY: "mi-local-data";
764
- export const SESSION_ID_KEY: "id";
765
- export const DEVICE_ID_KEY: "deviceId";
766
- export type SessionData = {
767
- [SESSION_ID_KEY]: string;
768
- [prop: string]: unknown;
769
- };
770
- export type LocalData = {
771
- [DEVICE_ID_KEY]: string;
772
- [prop: string]: unknown;
773
- };
774
- export class SafeStorage {
775
- #private;
776
- static getInstance(): SafeStorage;
777
- static ___clearInstance(): void;
778
- saveSessionData<T extends keyof SessionData>(key: T, data: SessionData[T]): boolean;
779
- loadSessionData<T extends keyof SessionData>(key: T): SessionData[T] extends undefined ? SessionData[T] | undefined : SessionData[T];
780
- saveLocalData<T extends keyof LocalData>(key: T, data: LocalData[T]): boolean;
781
- loadLocalData<T extends keyof LocalData>(key: T): LocalData[T] extends undefined ? LocalData[T] | undefined : LocalData[T];
782
- }
609
+ const partialSettings: PartialDeep<Settings, {recurseIntoArrays: true}> = {
610
+ languages: [undefined]
611
+ };
612
+ ```
613
+
614
+ @see {@link PartialDeepOptions}
615
+
616
+ @category Object
617
+ @category Array
618
+ @category Set
619
+ @category Map
620
+ */
621
+ type PartialDeep<T, Options extends PartialDeepOptions = {}> = _PartialDeep<T, ApplyDefaultOptions<PartialDeepOptions, DefaultPartialDeepOptions, Options>>;
622
+ type _PartialDeep<T, Options extends Required<PartialDeepOptions>> = T extends BuiltIns | ((new (...arguments_: any[]) => unknown)) ? T : IsNever<keyof T> extends true // For functions with no properties
623
+ ? T : T extends Map<infer KeyType, infer ValueType> ? PartialMapDeep<KeyType, ValueType, Options> : T extends Set<infer ItemType> ? PartialSetDeep<ItemType, Options> : T extends ReadonlyMap<infer KeyType, infer ValueType> ? PartialReadonlyMapDeep<KeyType, ValueType, Options> : T extends ReadonlySet<infer ItemType> ? PartialReadonlySetDeep<ItemType, Options> : T extends object ? T extends ReadonlyArray<infer ItemType> // Test for arrays/tuples, per https://github.com/microsoft/TypeScript/issues/35156
624
+ ? Options['recurseIntoArrays'] extends true ? ItemType[] extends T // Test for arrays (non-tuples) specifically
625
+ ? readonly ItemType[] extends T // Differentiate readonly and mutable arrays
626
+ ? ReadonlyArray<_PartialDeep<Options['allowUndefinedInNonTupleArrays'] extends false ? ItemType : ItemType | undefined, Options>> : Array<_PartialDeep<Options['allowUndefinedInNonTupleArrays'] extends false ? ItemType : ItemType | undefined, Options>> : PartialObjectDeep<T, Options> // Tuples behave properly
627
+ : T // If they don't opt into array testing, just use the original type
628
+ : PartialObjectDeep<T, Options> : unknown;
629
+
630
+ /**
631
+ Same as `PartialDeep`, but accepts only `Map`s and as inputs. Internal helper for `PartialDeep`.
632
+ */
633
+ type PartialMapDeep<KeyType$1, ValueType$1, Options extends Required<PartialDeepOptions>> = {} & Map<_PartialDeep<KeyType$1, Options>, _PartialDeep<ValueType$1, Options>>;
634
+
635
+ /**
636
+ Same as `PartialDeep`, but accepts only `Set`s as inputs. Internal helper for `PartialDeep`.
637
+ */
638
+ type PartialSetDeep<T, Options extends Required<PartialDeepOptions>> = {} & Set<_PartialDeep<T, Options>>;
639
+
640
+ /**
641
+ Same as `PartialDeep`, but accepts only `ReadonlyMap`s as inputs. Internal helper for `PartialDeep`.
642
+ */
643
+ type PartialReadonlyMapDeep<KeyType$1, ValueType$1, Options extends Required<PartialDeepOptions>> = {} & ReadonlyMap<_PartialDeep<KeyType$1, Options>, _PartialDeep<ValueType$1, Options>>;
644
+
645
+ /**
646
+ Same as `PartialDeep`, but accepts only `ReadonlySet`s as inputs. Internal helper for `PartialDeep`.
647
+ */
648
+ type PartialReadonlySetDeep<T, Options extends Required<PartialDeepOptions>> = {} & ReadonlySet<_PartialDeep<T, Options>>;
649
+
650
+ /**
651
+ Same as `PartialDeep`, but accepts only `object`s as inputs. Internal helper for `PartialDeep`.
652
+ */
653
+ type PartialObjectDeep<ObjectType extends object, Options extends Required<PartialDeepOptions>> = (ObjectType extends ((...arguments_: any) => unknown) ? (...arguments_: Parameters<ObjectType>) => ReturnType<ObjectType> : {}) & ({ [KeyType in keyof ObjectType]?: _PartialDeep<ObjectType[KeyType], Options> });
654
+ //#endregion
655
+ //#region ../../node_modules/.pnpm/type-fest@4.41.0/node_modules/type-fest/source/readonly-deep.d.ts
656
+ /**
657
+ Convert `object`s, `Map`s, `Set`s, and `Array`s and all of their keys/elements into immutable structures recursively.
658
+
659
+ This is useful when a deeply nested structure needs to be exposed as completely immutable, for example, an imported JSON module or when receiving an API response that is passed around.
660
+
661
+ Please upvote [this issue](https://github.com/microsoft/TypeScript/issues/13923) if you want to have this type as a built-in in TypeScript.
662
+
663
+ @example
664
+ ```
665
+ // data.json
666
+ {
667
+ "foo": ["bar"]
783
668
  }
784
669
 
785
- declare module '@mappedin/blue-dot/packages/common/color' {
786
- export const X11_COLOR_NAMES_SET: Set<string>;
787
- /**
788
- * Check if a string is a valid X11 color name, as defined in ThreeJS Color.NAMES
789
- * @param color - The color string to check.
790
- * @returns True if the color is a valid X11 color name, false otherwise.
791
- */
792
- export const isX11Color: (color: string) => boolean;
793
- /**
794
- * Check if a string is a valid hex color.
795
- * @param color - The color string to check.
796
- * @returns True if the color is a valid hex color, false otherwise.
797
- */
798
- export const isHexColor: (color: string) => boolean;
670
+ // main.ts
671
+ import type {ReadonlyDeep} from 'type-fest';
672
+ import dataJson = require('./data.json');
673
+
674
+ const data: ReadonlyDeep<typeof dataJson> = dataJson;
675
+
676
+ export default data;
677
+
678
+ // test.ts
679
+ import data from './main';
680
+
681
+ data.foo.push('bar');
682
+ //=> error TS2339: Property 'push' does not exist on type 'readonly string[]'
683
+ ```
684
+
685
+ Note that types containing overloaded functions are not made deeply readonly due to a [TypeScript limitation](https://github.com/microsoft/TypeScript/issues/29732).
686
+
687
+ @category Object
688
+ @category Array
689
+ @category Set
690
+ @category Map
691
+ */
692
+ type ReadonlyDeep<T> = T extends BuiltIns ? T : T extends (new (...arguments_: any[]) => unknown) ? T // Skip class constructors
693
+ : T extends ((...arguments_: any[]) => unknown) ? {} extends ReadonlyObjectDeep<T> ? T : HasMultipleCallSignatures<T> extends true ? T : ((...arguments_: Parameters<T>) => ReturnType<T>) & ReadonlyObjectDeep<T> : T extends Readonly<ReadonlyMap<infer KeyType, infer ValueType>> ? ReadonlyMapDeep<KeyType, ValueType> : T extends Readonly<ReadonlySet<infer ItemType>> ? ReadonlySetDeep<ItemType> :
694
+ // Identify tuples to avoid converting them to arrays inadvertently; special case `readonly [...never[]]`, as it emerges undesirably from recursive invocations of ReadonlyDeep below.
695
+ T extends readonly [] | readonly [...never[]] ? readonly [] : T extends readonly [infer U, ...infer V] ? readonly [ReadonlyDeep<U>, ...ReadonlyDeep<V>] : T extends readonly [...infer U, infer V] ? readonly [...ReadonlyDeep<U>, ReadonlyDeep<V>] : T extends ReadonlyArray<infer ItemType> ? ReadonlyArray<ReadonlyDeep<ItemType>> : T extends object ? ReadonlyObjectDeep<T> : unknown;
696
+ /**
697
+ Same as `ReadonlyDeep`, but accepts only `ReadonlyMap`s as inputs. Internal helper for `ReadonlyDeep`.
698
+ */
699
+ type ReadonlyMapDeep<KeyType$1, ValueType$1> = {} & Readonly<ReadonlyMap<ReadonlyDeep<KeyType$1>, ReadonlyDeep<ValueType$1>>>;
700
+
701
+ /**
702
+ Same as `ReadonlyDeep`, but accepts only `ReadonlySet`s as inputs. Internal helper for `ReadonlyDeep`.
703
+ */
704
+ type ReadonlySetDeep<ItemType$1> = {} & Readonly<ReadonlySet<ReadonlyDeep<ItemType$1>>>;
705
+
706
+ /**
707
+ Same as `ReadonlyDeep`, but accepts only `object`s as inputs. Internal helper for `ReadonlyDeep`.
708
+ */
709
+ type ReadonlyObjectDeep<ObjectType extends object> = { readonly [KeyType in keyof ObjectType]: ReadonlyDeep<ObjectType[KeyType]> };
710
+ //#endregion
711
+ //#region ../packages/common/extensions.d.ts
712
+ interface MapViewExtension<T> {
713
+ enable(options?: PartialDeep<T>): void;
714
+ disable(): void;
715
+ get isEnabled(): boolean;
716
+ destroy(): void;
717
+ }
718
+ //#endregion
719
+ //#region ../packages/common/pubsub.d.ts
720
+ /**
721
+ * Generic PubSub class implementing the Publish-Subscribe pattern for event handling.
722
+ *
723
+ * @template EVENT_PAYLOAD - The type of the event payload.
724
+ * @template EVENT - The type of the event.
725
+ */
726
+ declare class PubSub<EVENT_PAYLOAD, EVENT extends keyof EVENT_PAYLOAD = keyof EVENT_PAYLOAD> {
727
+ /**
728
+ * @private
729
+ * @internal
730
+ */
731
+ private _subscribers;
732
+ /**
733
+ * @private
734
+ * @internal
735
+ */
736
+ private _destroyed;
737
+ /**
738
+ * @private
739
+ * @internal
740
+ */
741
+ publish<EVENT_NAME extends EVENT>(eventName: EVENT_NAME, data?: EVENT_PAYLOAD[EVENT_NAME]): void;
742
+ /**
743
+ * Subscribe a function to an event.
744
+ *
745
+ * @param eventName An event name which, when fired, will call the provided
746
+ * function.
747
+ * @param fn A callback that gets called when the corresponding event is fired. The
748
+ * callback will get passed an argument with a type that's one of event payloads.
749
+ * @example
750
+ * // Subscribe to the 'click' event
751
+ * const handler = (event) => {
752
+ * const { coordinate } = event;
753
+ * const { latitude, longitude } = coordinate;
754
+ * console.log(`Map was clicked at ${latitude}, ${longitude}`);
755
+ * };
756
+ * map.on('click', handler);
757
+ */
758
+ on<EVENT_NAME extends EVENT>(eventName: EVENT_NAME, fn: (payload: EVENT_PAYLOAD[EVENT_NAME] extends {
759
+ data: null;
760
+ } ? EVENT_PAYLOAD[EVENT_NAME]['data'] : EVENT_PAYLOAD[EVENT_NAME]) => void): void;
761
+ /**
762
+ * Unsubscribe a function previously subscribed with {@link on}
763
+ *
764
+ * @param eventName An event name to which the provided function was previously
765
+ * subscribed.
766
+ * @param fn A function that was previously passed to {@link on}. The function must
767
+ * have the same reference as the function that was subscribed.
768
+ * @example
769
+ * // Unsubscribe from the 'click' event
770
+ * const handler = (event) => {
771
+ * console.log('Map was clicked', event);
772
+ * };
773
+ * map.off('click', handler);
774
+ */
775
+ off<EVENT_NAME extends EVENT>(eventName: EVENT_NAME, fn: (payload: EVENT_PAYLOAD[EVENT_NAME] extends {
776
+ data: null;
777
+ } ? EVENT_PAYLOAD[EVENT_NAME]['data'] : EVENT_PAYLOAD[EVENT_NAME]) => void): void;
778
+ /**
779
+ * @private
780
+ * @internal
781
+ */
782
+ destroy(): void;
783
+ }
784
+ //#endregion
785
+ //#region ../packages/common/interpolate.d.ts
786
+ declare const EASING_CURVES: readonly ["ease-in", "ease-out", "ease-in-out", "linear"];
787
+ type EasingCurve = (typeof EASING_CURVES)[number];
788
+ //#endregion
789
+ //#region src/types.d.ts
790
+ type FollowMode = /** Camera position follows the Blue Dot's position. */
791
+ 'position-only'
792
+ /** Camera position follows the Blue Dot's position. Camera bearing matches the Blue Dot's heading. */ | 'position-and-heading'
793
+ /** Camera position follows the Blue Dot's position. Camera bearing is calculated based on the Navigation path. */ | 'position-and-path-direction'
794
+ /** Disables follow mode */ | false;
795
+ type FollowCameraOptions = {
796
+ /**
797
+ * @default 21
798
+ */
799
+ zoomLevel?: number;
800
+ /**
801
+ * @default 45
802
+ */
803
+ pitch?: number;
804
+ /**
805
+ * Camera bearing in degrees clockwise from North. 0 is North, 90 is East, 180 is South, 270 is West.
806
+ * This option is only available in 'position-only' mode. In all other modes, the bearing will be calculated automatically.
807
+ * @default undefined
808
+ */
809
+ bearing?: number;
810
+ /**
811
+ * @default undefined
812
+ */
813
+ elevation?: number;
814
+ /**
815
+ * @default 1000
816
+ */
817
+ duration?: number;
818
+ /**
819
+ * @default 'ease-in-out'
820
+ */
821
+ easing?: EasingCurve;
822
+ };
823
+ type BlueDotEventPayloads = {
824
+ /**
825
+ * Emitted when the Blue Dot's position is updated either from the device's geolocation API or by calling {@link BlueDot.update}.
826
+ * see {@link BlueDot.watchDevicePosition} for more details.
827
+ */
828
+ 'position-update': {
829
+ floor: Floor | undefined;
830
+ heading: GeolocationPosition['coords']['heading'] | undefined;
831
+ accuracy: GeolocationPosition['coords']['accuracy'] | undefined;
832
+ coordinate: Coordinate;
833
+ };
834
+ /**
835
+ * Emitted when the device's orientation changes and the Blue Dot's heading is updated.
836
+ * see {@link BlueDot.watchDeviceOrientation} for more details.
837
+ */
838
+ 'device-orientation-update': {
839
+ heading: GeolocationPosition['coords']['heading'] | undefined;
840
+ };
841
+ /**
842
+ * Emitted when the Blue Dot's status changes.
843
+ */
844
+ 'status-change': {
799
845
  /**
800
- * Check if a string is a valid RGB/RGBA color.
801
- * @param color - The color string to check.
802
- * @returns True if the color is a valid RGB/RGBA color, false otherwise.
803
- */
804
- export const isRgbColor: (color: string) => boolean;
846
+ * The new status of the Blue Dot.
847
+ */
848
+ status: BlueDotStatus;
805
849
  /**
806
- * Check if a string is a valid HSL/HSLA color.
807
- * @param color - The color string to check.
808
- * @returns True if the color is a valid HSL/HSLA color, false otherwise.
809
- */
810
- export const isHslColor: (color: string) => boolean;
850
+ * The action that caused the status change.
851
+ */
852
+ action: BlueDotAction;
853
+ };
854
+ /**
855
+ * Emitted when the Blue Dot encounters an error.
856
+ */
857
+ error: GeolocationPositionError;
858
+ /**
859
+ * Emitted when the Blue Dot's following state changes.
860
+ */
861
+ 'follow-change': {
811
862
  /**
812
- * Check if a string is a valid ThreeJS color. Can be hex, rgb, rgba, hsl, hsla, or X11 color name.
813
- * @param color - The color string to check.
814
- * @returns True if the color is a valid ThreeJS color, false otherwise.
815
- */
816
- export const isColor: (color: string) => boolean;
863
+ * Whether the Blue Dot is following the user.
864
+ */
865
+ following: boolean;
817
866
  /**
818
- * Convert a color string to an array of RGB values.
819
- * @param color - The color string to convert.
820
- * @returns The array of RGB values.
821
- */
822
- export const stringToRgbArray: (color: string) => [number, number, number];
867
+ * The mode the Blue Dot is following the user in.
868
+ */
869
+ mode?: FollowMode;
870
+ };
871
+ /**
872
+ * Emitted when the user clicks on the Blue Dot.
873
+ */
874
+ click: {
875
+ coordinate: Coordinate;
876
+ };
877
+ /**
878
+ * Emitted when the user hovers over the Blue Dot.
879
+ */
880
+ hover: {
881
+ coordinate: Coordinate;
882
+ };
883
+ };
884
+ type BlueDotEvents = keyof BlueDotEventPayloads;
885
+ type BlueDotStatus = 'hidden' | 'active' | 'inactive' | 'disabled';
886
+ type BlueDotAction = 'timeout' | 'error' | 'position-update' | 'enable' | 'disable' | 'initialize';
887
+ type BlueDotState = {
888
+ /**
889
+ * The radius of the BlueDot in pixels. The BlueDot will maintain this size clamped to a minimum of 0.35 metres.
890
+ * @default 10
891
+ */
892
+ radius: number;
893
+ /**
894
+ * The color of the BlueDot core element.
895
+ * @default #2266ff
896
+ */
897
+ color: string;
898
+ /**
899
+ * The color of the BlueDot when it has timed out and gone inactive.
900
+ * @default #808080
901
+ */
902
+ inactiveColor: string;
903
+ /**
904
+ * Options for the accuracy ring around the BlueDot.
905
+ */
906
+ accuracyRing: {
823
907
  /**
824
- * Convert an array of RGB values to a hex string.
825
- * @param rgb - The array of RGB values to convert.
826
- * @returns The hex string representation of the RGB values.
827
- */
828
- export const rgbArrayToString: (rgb: [number, number, number]) => string;
829
- }
830
-
831
- declare module '@mappedin/blue-dot/packages/common/interpolate' {
832
- export const EASING_CURVES: readonly ["ease-in", "ease-out", "ease-in-out", "linear"];
833
- export type EasingCurve = (typeof EASING_CURVES)[number];
908
+ * The color of the accuracy ring.
909
+ * @default #2266ff
910
+ */
911
+ color: string;
834
912
  /**
835
- * Validates if a value is a valid easing curve
836
- * @param value The value to validate
837
- * @returns True if the value is a valid easing curve
838
- */
839
- export function isValidEasingCurve(value: unknown): value is EasingCurve;
840
- export const linearEase: (t: number) => number;
841
- export const quadEaseIn: (t: number) => number;
842
- export const easeIn: (x: number) => number;
843
- export const quadEaseOut: (t: number) => number;
844
- export function interpolate(value: number, inputMin: number, inputMax: number, outputMin: number, outputMax: number, easeFunc?: EasingCurve | ((t: number) => number)): number;
913
+ * The opacity of the accuracy ring.
914
+ * @default 0.3
915
+ */
916
+ opacity: number;
917
+ };
918
+ /**
919
+ * Options for the heading directional indicator.
920
+ */
921
+ heading: {
845
922
  /**
846
- * Return the closest range within an ordered set of values that a given value falls within. If the given value is
847
- * exactly within a range, returns the index of the range. If the given value is less than the first value in the range,
848
- * returns 0. If the given value is greater than the last value in the range, returns the last range (lastIndex - 1).
849
- */
850
- export function getInterpolationBreakpoint(value: number, range: number[]): number;
851
- export function interpolateMulti(value: number, inputRange: number[], outputRange: number[], easeFunc?: EasingCurve | ((t: number) => number)): number;
852
- }
853
-
854
- declare module '@mappedin/blue-dot/packages/common/math-utils' {
923
+ * The color of the heading cone.
924
+ * @default #2266ff
925
+ */
926
+ color: string;
855
927
  /**
856
- * Clamp a number between lower and upper bounds with a warning
857
- */
858
- export function clampWithWarning(x: number, lower: number, upper: number, warning: string): number;
859
- }
860
-
861
- declare module '@mappedin/blue-dot/packages/common/array-utils' {
928
+ * The opacity of the heading cone.
929
+ * @default 0.7
930
+ */
931
+ opacity: number;
862
932
  /**
863
- * Compare two arrays for equality
864
- */
865
- export function arraysEqual(arr1: any[] | null | undefined, arr2: any[] | null | undefined): boolean;
933
+ * Whether to display the heading cone when the BlueDot is inactive (timed out).
934
+ * @default false
935
+ */
936
+ displayWhenInactive: boolean;
937
+ };
938
+ /**
939
+ * The duration of the timeout in milliseconds.
940
+ * If the BlueDot does not receive a position update within this time, it will grey out until a position is received.
941
+ * @default 30000
942
+ */
943
+ timeout: number;
944
+ /**
945
+ * Whether to watch the device's position.
946
+ * @default true
947
+ */
948
+ watchDevicePosition: boolean;
949
+ /**
950
+ * Whether to log debug messages.
951
+ * @default false
952
+ */
953
+ debug: boolean;
954
+ /**
955
+ * The maximum acceptable accuracy in meters. Position updates with accuracy exceeding this value will be dropped.
956
+ * @default 50
957
+ */
958
+ accuracyThreshold: number;
959
+ /**
960
+ * The initial state of the BlueDot when enabled.
961
+ * @default 'hidden'
962
+ */
963
+ initialState: 'hidden' | 'inactive';
964
+ /**
965
+ * @hidden
966
+ * Whether the BlueDot must remain within the map bounds. Disabling this will disable analytics as well.
967
+ * @default true
968
+ */
969
+ preventOutOfBounds: boolean;
970
+ };
971
+ type BlueDotUpdateState = PartialDeep<BlueDotState>;
972
+ /**
973
+ * Position update options for the {@link BlueDot.update} method.
974
+ */
975
+ type BlueDotPositionUpdate = {
976
+ /**
977
+ * Latitude to override.
978
+ * Set to `'device'` to reset to the device's latitude.
979
+ */
980
+ latitude?: GeolocationPosition['coords']['latitude'] | 'device' | undefined;
981
+ /**
982
+ * Longitude to override.
983
+ * Set to `'device'` to reset to the device's longitude.
984
+ */
985
+ longitude?: GeolocationPosition['coords']['longitude'] | 'device' | undefined;
986
+ /**
987
+ * Accuracy to override.
988
+ * Set to `'device'` to reset to the device's accuracy.
989
+ * Set to `undefined` to disable the accuracy ring.
990
+ */
991
+ accuracy?: GeolocationPosition['coords']['accuracy'] | 'device' | undefined;
992
+ /**
993
+ * Heading to override.
994
+ * Set to `'device'` to reset to the device's heading.
995
+ * Set to `undefined` to disable the heading indicator.
996
+ */
997
+ heading?: GeolocationPosition['coords']['heading'] | 'device' | undefined;
998
+ /**
999
+ * Floor or floorId to override.
1000
+ * Set to `'device'` to reset to the device's floor level.
1001
+ * Set to `undefined` to disable floor level and show the BlueDot on all floors.
1002
+ */
1003
+ floorOrFloorId?: Floor | string | 'device' | undefined;
1004
+ /**
1005
+ * Timestamp of the position update in milliseconds.
1006
+ */
1007
+ timestamp?: number;
1008
+ };
1009
+ type BlueDotPositionUpdateWithFloor = Omit<BlueDotPositionUpdate, 'floorOrFloorId'> & {
1010
+ floor?: Floor | 'device' | undefined;
1011
+ };
1012
+ type BlueDotPositionProcessor = (current: BlueDotPositionUpdateWithFloor, incoming: BlueDotPositionUpdateWithFloor) => BlueDotPositionUpdateWithFloor | undefined;
1013
+ /**
1014
+ * Options for the BlueDot update method.
1015
+ */
1016
+ type BlueDotUpdateOptions = {
1017
+ /**
1018
+ * If true, maintains the current state and skips timers and analytics for this update.
1019
+ * @default false
1020
+ */
1021
+ silent?: boolean;
1022
+ /**
1023
+ * If true, animates the position change. If false, updates immediately.
1024
+ * @default true
1025
+ */
1026
+ animate?: boolean;
1027
+ };
1028
+ type GeolocationPositionExtended = GeolocationPosition & {
1029
+ coords: GeolocationPosition['coords'] & {
1030
+ readonly floorLevel?: number;
1031
+ };
1032
+ };
1033
+ //#endregion
1034
+ //#region src/blue-dot.d.ts
1035
+ /**
1036
+ * Show a Blue Dot indicating the device's position on the map.
1037
+ *
1038
+ * @example
1039
+ * ```ts
1040
+ * import { show3dMap } from '@mappedin/mappedin-js';
1041
+ * import { BlueDot } from '@mappedin/blue-dot';
1042
+ *
1043
+ * const mapView = await show3dMap(...);
1044
+ *
1045
+ * // Enable BlueDot
1046
+ * const blueDot = new BlueDot(mapView).enable();
1047
+ *
1048
+ * // Option 1: Listen for position updates from the device
1049
+ * blueDot.on('position-update', (position) => {
1050
+ * console.log('User position:', position);
1051
+ * });
1052
+ *
1053
+ * // Option 2: Update position manually
1054
+ * blueDot.update({ latitude, longitude, accuracy, floorOrFloorId });
1055
+ *
1056
+ * ```
1057
+ */
1058
+ declare class BlueDot implements MapViewExtension<BlueDotState> {
1059
+ #private;
1060
+ /**
1061
+ * Create a new {@link BlueDot} instance.
1062
+ */
1063
+ constructor(mapView: MapView);
1064
+ /**
1065
+ * Get the Model for the BlueDot core element.
1066
+ */
1067
+ get dotModel(): Model | undefined;
1068
+ /**
1069
+ * Get the Model for the accuracy ring.
1070
+ */
1071
+ get accuracyRingModel(): Model | undefined;
1072
+ /**
1073
+ * Get the Model for the heading cone.
1074
+ */
1075
+ get headingConeModel(): Model | undefined;
1076
+ /**
1077
+ * Whether the BlueDot is currently enabled.
1078
+ */
1079
+ get isEnabled(): boolean;
1080
+ /**
1081
+ * The current state of the BlueDot. Can be 'hidden', 'active', 'inactive', or 'disabled'.
1082
+ * Listen for state changes using the 'status-change' event.
1083
+ *
1084
+ * @example
1085
+ * mapView.BlueDot.on('status-change', ({ status }) => {
1086
+ * if (status === 'active') {
1087
+ * // BlueDot is visible and tracking
1088
+ * }
1089
+ * });
1090
+ */
1091
+ get status(): BlueDotStatus;
1092
+ /**
1093
+ * Whether the BlueDot is currently following the user (camera follow mode).
1094
+ */
1095
+ get isFollowing(): boolean;
1096
+ /**
1097
+ * The direction the user is facing in degrees from north clockwise.
1098
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/GeolocationCoordinates/heading
1099
+ */
1100
+ get heading(): GeolocationPosition['coords']['heading'] | undefined;
1101
+ /**
1102
+ * The accuracy of the current position in metres.
1103
+ */
1104
+ get accuracy(): GeolocationPosition['coords']['accuracy'] | undefined;
1105
+ /**
1106
+ * The coordinate of the current position.
1107
+ */
1108
+ get coordinate(): Coordinate | undefined;
1109
+ /**
1110
+ * Returns the current Blue Dot state.
1111
+ */
1112
+ getState(): ReadonlyDeep<BlueDotState>;
1113
+ /**
1114
+ * The floor the Blue Dot is currently on. If undefined, the Blue Dot will appear on every floor.
1115
+ */
1116
+ get floor(): Floor | undefined;
1117
+ /**
1118
+ * Enable the Blue Dot. It will be hidden until a position is received either from the browser or by calling {@link BlueDot.update}.
1119
+ * @param options - The options to setup the Blue Dot (see {@link BlueDotUpdateState}).
1120
+ *
1121
+ * @example Enable with default options
1122
+ * ```ts
1123
+ * const blueDot = new BlueDot(mapView);
1124
+ * blueDot.enable();
1125
+ * ```
1126
+ * @example Enable with custom color and accuracy ring
1127
+ * ```ts
1128
+ * const blueDot = new BlueDot(mapView);
1129
+ * blueDot.enable({ color: '#00ff00', accuracyRing: { color: '#00ff00', opacity: 0.2 } });
1130
+ * ```
1131
+ *
1132
+ * @see See the [BlueDot Guide](https://developer.mappedin.com/web-sdk/blue-dot) for more information.
1133
+ */
1134
+ enable: (options?: BlueDotUpdateState) => void;
1135
+ /**
1136
+ * Disable the Blue Dot. It will be hidden and no longer update.
1137
+ */
1138
+ disable: () => void;
1139
+ /**
1140
+ * Subscribe to a BlueDot event.
1141
+ * @param eventName The name of the event to listen for.
1142
+ * @param fn The function to call when the event is emitted.
1143
+ */
1144
+ on: PubSub<BlueDotEventPayloads>['on'];
1145
+ /**
1146
+ * Unsubscribe from a BlueDot event.
1147
+ * @param eventName The name of the event to unsubscribe from.
1148
+ * @param fn The function to unsubscribe from the event.
1149
+ */
1150
+ off: PubSub<BlueDotEventPayloads>['off'];
1151
+ /**
1152
+ * Update the BlueDot state after it has been enabled.
1153
+ * This allows overriding previously set values like colors, and other options.
1154
+ * @param options - The options to update
1155
+ *
1156
+ * @example Update color and accuracy ring
1157
+ * ```ts
1158
+ * const blueDot = new BlueDot(mapView);
1159
+ * blueDot.updateState({
1160
+ * color: '#ff0000',
1161
+ * accuracyRing: { color: '#ff0000', opacity: 0.5 }
1162
+ * });
1163
+ * ```
1164
+ */
1165
+ updateState: (options: BlueDotUpdateState) => void;
1166
+ /**
1167
+ * Enable or disable the devices's geolocation listener to automatically position the Blue Dot.
1168
+ * If enabled, the device will request permission to access the user's precise location.
1169
+ *
1170
+ * @remarks This will emit a 'position-update' event every time a new position is received.
1171
+ *
1172
+ * @param watch - Whether to enable or disable the listener.
1173
+ */
1174
+ watchDevicePosition: (watch: boolean) => void;
1175
+ /**
1176
+ * Enable or disable the device orientation listener to automatically update the Blue Dot's heading.
1177
+ * This must be enabled in response to a user action such as a tap or click and cannot be enabled automatically.
1178
+ *
1179
+ * @remarks This will emit a 'device-orientation-update' event every time the device's orientation changes.
1180
+ * Device orientation changes will not emit a 'position-update' event.
1181
+ *
1182
+ * @see https://www.w3.org/TR/orientation-event/#dom-deviceorientationevent-requestpermission
1183
+ *
1184
+ * @param watch - Whether to enable or disable the listener.
1185
+ *
1186
+ * @example Enable device orientation listener
1187
+ * ```ts
1188
+ * const blueDot = new BlueDot(mapView);
1189
+ * // Enable device orientation on button click
1190
+ * button.addEventListener('click', () => {
1191
+ * blueDot.watchDeviceOrientation(true);
1192
+ * });
1193
+ * ```
1194
+ */
1195
+ watchDeviceOrientation: (watch: boolean) => Promise<void>;
1196
+ /**
1197
+ * Manually override some position properties of the Blue Dot.
1198
+ * Accepts a full GeolocationPosition object or a partial {@link BlueDotPositionUpdate} object.
1199
+ *
1200
+ * @remarks This will emit a 'position-update' event.
1201
+ *
1202
+ * @example Manually set the accuracy and heading
1203
+ * ```ts
1204
+ * api.BlueDot.update({ accuracy: 10, heading: 90 });
1205
+ * ```
1206
+ * @example Reset accuracy and heading to device values
1207
+ * ```ts
1208
+ * api.BlueDot.update({ accuracy: 'device', heading: 'device' });
1209
+ * ```
1210
+ */
1211
+ update: (position: GeolocationPositionExtended | BlueDotPositionUpdate | undefined, options?: BlueDotUpdateOptions) => void;
1212
+ /**
1213
+ * Set the camera to follow the BlueDot in various modes. User interaction will cancel following automatically.
1214
+ * @param mode The follow mode ('position-only', 'position-and-heading', 'position-and-path-direction', or false to disable).
1215
+ * @param cameraOptions Optional camera options (zoom, pitch, etc.).
1216
+ *
1217
+ * @example
1218
+ * mapView.BlueDot.follow('position-and-heading', { zoomLevel: 21, pitch: 45 });
1219
+ */
1220
+ follow: (mode: FollowMode, cameraOptions?: FollowCameraOptions) => void;
1221
+ /**
1222
+ * Set a position processor callback that allows intercepting and modifying device/geolocation position updates before they are applied.
1223
+ *
1224
+ * **Note**: This processor only applies to automatic position updates from device geolocation.
1225
+ * Manual position updates via `update()` method bypass the processor and are applied directly.
1226
+ *
1227
+ * @param processor - A callback function that receives current state and incoming update. Return undefined to discard the update, or return a modified update object.
1228
+ *
1229
+ * @example Discard inaccurate positions
1230
+ * ```ts
1231
+ * blueDot.setPositionProcessor((current, incoming) => {
1232
+ * if (incoming.accuracy && incoming.accuracy > 50) {
1233
+ * return undefined; // Discard update
1234
+ * }
1235
+ * return incoming; // Accept update
1236
+ * });
1237
+ * ```
1238
+ *
1239
+ * @example Modify incoming positions
1240
+ * ```ts
1241
+ * blueDot.setPositionProcessor((current, incoming) => {
1242
+ * // Apply custom smoothing or validation logic
1243
+ * return {
1244
+ * ...incoming,
1245
+ * accuracy: Math.min(incoming.accuracy || 100, 10) // Cap accuracy
1246
+ * };
1247
+ * });
1248
+ * ```
1249
+ */
1250
+ setPositionProcessor(processor?: BlueDotPositionProcessor): void;
1251
+ destroy: () => void;
1252
+ private onPositionUpdate;
1253
+ private onPositionError;
866
1254
  }
867
-
1255
+ //#endregion
1256
+ export { BlueDot, type BlueDotAction, type BlueDotEventPayloads, type BlueDotEvents, type BlueDotPositionProcessor, type BlueDotPositionUpdate, type BlueDotPositionUpdateWithFloor, type BlueDotState, type BlueDotStatus, type BlueDotUpdateOptions, type FollowCameraOptions, type FollowMode, type GeolocationPositionExtended };