@mappedin/dynamic-focus 6.0.1-beta.59 → 6.0.1-beta.61

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts", "../src/dynamic-focus.ts", "../../packages/common/array-utils.ts", "../../packages/common/pubsub.ts", "../src/building.ts", "../src/dynamic-focus-scene.ts", "../src/types.ts", "../src/validation.ts", "../../packages/common/Mappedin.Logger.ts", "../../packages/common/math-utils.ts", "../src/logger.ts", "../src/outdoors.ts", "../src/constants.ts"],
4
- "sourcesContent": ["export { DynamicFocus } from './dynamic-focus';\nexport type {\n\tDynamicFocusState,\n\tDynamicFocusMode,\n\tDynamicFocusAnimationOptions,\n\tDynamicFocusEvents,\n\tDynamicFocusEventPayload,\n} from './types';\n", "import type {\n\tCameraTransform,\n\tFacade,\n\tFloorStack,\n\tMapData,\n\tMapView,\n\tTEvents,\n\tTFloorState,\n} from '@mappedin/mappedin-js';\nimport { Floor, getMultiFloorState } from '@mappedin/mappedin-js';\nimport { arraysEqual } from '@packages/internal/common/array-utils';\nimport { PubSub } from '@packages/internal/common/pubsub';\nimport { Building } from './building';\nimport {\n\tgetFloorToShow,\n\tshouldShowIndoor,\n\tgetBuildingAnimationType,\n\tgetZoomState,\n\tgetOutdoorOpacity,\n\tgetSetFloorTargetFromZoomState,\n\tgetBuildingStates,\n\tshouldDeferSetFloor,\n} from './dynamic-focus-scene';\nimport { DYNAMIC_FOCUS_MODES } from './types';\nimport type {\n\tViewState,\n\tZoomState,\n\tBuildingFacadeState,\n\tDynamicFocusEventPayload,\n\tDynamicFocusEvents,\n\tDynamicFocusMode,\n\tDynamicFocusState,\n\tBuildingFloorStackState,\n\tInternalDynamicFocusEvents,\n} from './types';\nimport { validateFloorForStack, validateZoomThreshold } from './validation';\nimport { getOutdoorFloorStack, Outdoors } from './outdoors';\nimport { Logger } from './logger';\nimport MappedinJSLogger from '../../packages/common/Mappedin.Logger';\nimport { DEFAULT_STATE } from './constants';\nimport type { MapViewExtension } from '@packages/internal/common/extensions';\n\n/**\n * Dynamic Focus is a MapView scene manager that maintains the visibility of the outdoors\n * while fading in and out building interiors as the camera pans.\n */\nexport class DynamicFocus implements MapViewExtension<DynamicFocusState> {\n\t#pubsub: PubSub<DynamicFocusEvents & InternalDynamicFocusEvents>;\n\t#mapView: MapView;\n\t#mapData: MapData;\n\t#state: Required<DynamicFocusState> = DEFAULT_STATE;\n\t/**\n\t * The buildings that are currently in view, sorted by the order they are in the facades-in-view-change event.\n\t * While these will be within the camera view, these may not be in focus or showIndoor depending on the mode.\n\t */\n\t#sortedBuildingsInView: Building[] = [];\n\t/**\n\t * The buildings that are currently in view, as a set of building ids.\n\t */\n\t#buildingIdsInViewSet = new Set<string>();\n\t#buildings = new Map<string, Building>();\n\t#outdoors: Outdoors;\n\t#userInteracting = false;\n\t#pendingFacadeUpdate = false;\n\t#floorElevation = 0;\n\t#cameraElevation = 0;\n\t/**\n\t * Tracks the current zoom state based on camera zoom level:\n\t * - 'in-range': Camera is zoomed in enough to show indoor details (>= indoorZoomThreshold)\n\t * - 'out-of-range': Camera is zoomed out to show outdoor context (<= outdoorZoomThreshold)\n\t * - 'transition': Camera is between the two thresholds (no floor changes occur)\n\t */\n\t#zoomState: ZoomState = 'transition';\n\t#viewState: ViewState = 'outdoor';\n\t/**\n\t * The facades that are actually focused and shown (filtered by showIndoor logic)\n\t */\n\t#facadesInFocus: Facade[] = [];\n\t#enabled = false;\n\n\t/**\n\t * @internal\n\t * Used to await the current scene update before starting a new one, or when the scene is updated asynchronously by an event.\n\t */\n\tprivate sceneUpdateQueue: Promise<void> = Promise.resolve();\n\n\t/**\n\t * Creates a new instance of the Dynamic Focus controller.\n\t *\n\t * @param mapView - The {@link MapView} to attach Dynamic Focus to.\n\t * @param options - Options for configuring Dynamic Focus.\n\t *\n\t * @example\n\t * ```ts\n\t * const mapView = show3dMap(...);\n\t * const df = new DynamicFocus(mapView);\n\t * df.enable({ autoFocus: true });\n\t *\n\t * // pause the listener\n\t * df.updateState({ autoFocus: false });\n\t *\n\t * // manually trigger a focus\n\t * df.focus();\n\t * ```\n\t */\n\tconstructor(mapView: MapView) {\n\t\tthis.#pubsub = new PubSub<DynamicFocusEvents & InternalDynamicFocusEvents>();\n\t\tthis.#mapView = mapView;\n\t\tLogger.setLevel(MappedinJSLogger.logState);\n\t\tthis.#mapData = this.#mapView.getMapData();\n\t\tthis.#floorElevation = this.#mapView.currentFloor.elevation;\n\t\tthis.#cameraElevation = this.#mapView.Camera.elevation;\n\t\t// initialize the buildings\n\t\tfor (const facade of this.#mapData.getByType('facade')) {\n\t\t\tthis.#buildings.set(facade.floorStack.id, new Building(facade.floorStack, this.#mapView));\n\t\t}\n\t\tthis.#outdoors = new Outdoors(\n\t\t\tgetOutdoorFloorStack(this.#mapData.getByType('floor-stack'), this.#buildings),\n\t\t\tthis.#mapView,\n\t\t);\n\t\tthis.#mapView.on('floor-change-start', this.#handleFloorChangeStart);\n\t\tthis.#mapView.on('camera-change', this.#handleCameraChange);\n\t\tthis.#mapView.on('facades-in-view-change', this.#handleFacadesInViewChange);\n\t\tthis.#mapView.on('user-interaction-start', this.#handleUserInteractionStart);\n\t\tthis.#mapView.on('user-interaction-end', this.#handleUserInteractionEnd);\n\t}\n\n\t/**\n\t * Enables Dynamic Focus with the given options.\n\t * @param options - The options to enable Dynamic Focus with.\n\t */\n\tenable(options?: Partial<DynamicFocusState>): void {\n\t\tif (this.#enabled) {\n\t\t\tLogger.warn('enable() called on an already enabled Dynamic Focus instance.');\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#enabled = true;\n\t\tthis.#mapView.manualFloorVisibility = true;\n\t\tthis.#outdoors.show();\n\t\tthis.updateState({ ...this.#state, ...options });\n\t\t// fire the camera change event to set the initial state\n\t\tthis.#handleCameraChange({\n\t\t\tzoomLevel: this.#mapView.Camera.zoomLevel,\n\t\t\tcenter: this.#mapView.Camera.center,\n\t\t\tbearing: this.#mapView.Camera.bearing,\n\t\t\tpitch: this.#mapView.Camera.pitch,\n\t\t} as CameraTransform);\n\t\t// fire dynamic focus change to set initial state of facades\n\t\tthis.#mapView.Camera.updateFacadesInView();\n\t}\n\t/**\n\t * Disables Dynamic Focus and returns the MapView to it's previous state.\n\t */\n\tdisable(): void {\n\t\tif (!this.#enabled) {\n\t\t\tLogger.warn('disable() called on an already disabled Dynamic Focus instance.');\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#enabled = false;\n\t\tthis.#mapView.manualFloorVisibility = false;\n\t}\n\n\t/**\n\t * Returns true if Dynamic Focus is enabled.\n\t */\n\tget isEnabled(): boolean {\n\t\treturn this.#enabled;\n\t}\n\n\t/**\n\t * Returns true if the current view state is indoor.\n\t */\n\tget isIndoor() {\n\t\treturn this.#viewState === 'indoor';\n\t}\n\n\t/**\n\t * Returns true if the current view state is outdoor.\n\t */\n\tget isOutdoor() {\n\t\treturn this.#viewState === 'outdoor';\n\t}\n\n\t/**\n\t * Sets the view state to indoor, regardless of the current zoom level.\n\t */\n\tsetIndoor() {\n\t\tthis.#viewState = 'indoor';\n\t\tthis.#zoomState = 'in-range';\n\n\t\tthis.#handleViewStateChange();\n\t}\n\n\t/**\n\t * Sets the view state to outdoor, regardless of the current zoom level.\n\t */\n\tsetOutdoor() {\n\t\tthis.#viewState = 'outdoor';\n\t\tthis.#zoomState = 'out-of-range';\n\n\t\tthis.#handleViewStateChange();\n\t}\n\n\t#handleViewStateChange() {\n\t\tif (this.#state.autoFocus) {\n\t\t\t// Only set the floor if setFloorOnFocus is true and the view state changed due to a user interaction\n\t\t\t// Camera animations will not trigger a focus change until they settle.\n\t\t\tif (this.#userInteracting) {\n\t\t\t\tthis.focus();\n\t\t\t} else {\n\t\t\t\tthis.#pendingFacadeUpdate = true;\n\t\t\t}\n\t\t}\n\t\tthis.#pubsub.publish('state-change');\n\t}\n\n\t#preloadFloors(mode: DynamicFocusMode) {\n\t\tthis.#mapView.preloadFloors(\n\t\t\tthis.#mapData\n\t\t\t\t.getByType('facade')\n\t\t\t\t.map(facade => getFloorToShow(this.#buildings.get(facade.floorStack.id)!, mode, this.#floorElevation))\n\t\t\t\t.filter(f => f != null && Floor.is(f)),\n\t\t);\n\t}\n\n\t/**\n\t * Returns the facades that are currently in focus.\n\t */\n\tget focusedFacades() {\n\t\treturn [...this.#facadesInFocus];\n\t}\n\n\t/**\n\t * Subscribe to a Dynamic Focus event.\n\t */\n\ton = <EventName extends keyof DynamicFocusEvents>(\n\t\teventName: EventName,\n\t\tfn: (payload: DynamicFocusEventPayload<EventName>) => void,\n\t) => {\n\t\tthis.#pubsub.on(eventName, fn);\n\t};\n\n\t/**\n\t * Unsubscribe from a Dynamic Focus event.\n\t */\n\toff = <EventName extends keyof DynamicFocusEvents>(\n\t\teventName: EventName,\n\t\tfn: (payload: DynamicFocusEventPayload<EventName>) => void,\n\t) => {\n\t\tthis.#pubsub.off(eventName, fn);\n\t};\n\n\t/**\n\t * Returns the current state of the Dynamic Focus controller.\n\t */\n\tgetState(): DynamicFocusState {\n\t\treturn { ...this.#state };\n\t}\n\n\t/**\n\t * Updates the state of the Dynamic Focus controller.\n\t * @param state - The state to update.\n\t */\n\tupdateState(state: Partial<DynamicFocusState>) {\n\t\tlet shouldReapplyBuildingStates = false;\n\n\t\tif (state.indoorZoomThreshold != null) {\n\t\t\tstate.indoorZoomThreshold = validateZoomThreshold(\n\t\t\t\tstate.indoorZoomThreshold,\n\t\t\t\tthis.#state.outdoorZoomThreshold,\n\t\t\t\tthis.#mapView.Camera.maxZoomLevel,\n\t\t\t\t'indoorZoomThreshold',\n\t\t\t);\n\t\t}\n\t\tif (state.outdoorZoomThreshold != null) {\n\t\t\tstate.outdoorZoomThreshold = validateZoomThreshold(\n\t\t\t\tstate.outdoorZoomThreshold,\n\t\t\t\tthis.#mapView.Camera.minZoomLevel,\n\t\t\t\tthis.#state.indoorZoomThreshold,\n\t\t\t\t'outdoorZoomThreshold',\n\t\t\t);\n\t\t}\n\n\t\tif (state.mode != null) {\n\t\t\tstate.mode = DYNAMIC_FOCUS_MODES.includes(state.mode) ? state.mode : 'default-floor';\n\t\t}\n\n\t\tif (state.autoAdjustFacadeHeights != null) {\n\t\t\tthis.#state.autoAdjustFacadeHeights = state.autoAdjustFacadeHeights;\n\t\t}\n\n\t\tif (\n\t\t\tstate.dynamicBuildingInteriors != null &&\n\t\t\tstate.dynamicBuildingInteriors !== this.#state.dynamicBuildingInteriors\n\t\t) {\n\t\t\tshouldReapplyBuildingStates = true;\n\t\t}\n\n\t\t// assign state and ignore undefined values\n\t\tthis.#state = Object.assign(\n\t\t\t{},\n\t\t\tthis.#state,\n\t\t\tObject.fromEntries(Object.entries(state).filter(([, value]) => value != null)),\n\t\t);\n\n\t\t// preload the initial floors that will be included in the mode\n\t\tif (state.mode != null && state.preloadFloors) {\n\t\t\tthis.#preloadFloors(state.mode);\n\t\t}\n\n\t\tif (shouldReapplyBuildingStates) {\n\t\t\tthis.#applyBuildingStates();\n\t\t}\n\t}\n\n\t/**\n\t * Destroys the Dynamic Focus instance and unsubscribes all MapView event listeners.\n\t */\n\tdestroy() {\n\t\tthis.disable();\n\t\tthis.#mapView.off('facades-in-view-change', this.#handleFacadesInViewChange);\n\t\tthis.#mapView.off('floor-change-start', this.#handleFloorChangeStart);\n\t\tthis.#mapView.off('camera-change', this.#handleCameraChange);\n\t\tthis.#mapView.off('user-interaction-start', this.#handleUserInteractionStart);\n\t\tthis.#mapView.off('user-interaction-end', this.#handleUserInteractionEnd);\n\t\tthis.#buildings.forEach(building => building.destroy());\n\t\tthis.#outdoors.destroy();\n\t\tthis.#pubsub.destroy();\n\t}\n\n\t/**\n\t * Perform a manual visual update of the focused facades, and optionally set the floor.\n\t * @param setFloor - Whether to set the floor. This will default to the current state of setFloorOnFocus.\n\t */\n\tasync focus(setFloor = this.#state.setFloorOnFocus) {\n\t\tif (setFloor) {\n\t\t\tif (shouldDeferSetFloor(this.#cameraElevation, this.#mapView.Camera.elevation, this.#userInteracting)) {\n\t\t\t\tthis.#cameraElevation = this.#mapView.Camera.elevation;\n\t\t\t\tthis.#pendingFacadeUpdate = true;\n\t\t\t} else {\n\t\t\t\tconst target = getSetFloorTargetFromZoomState(this.#sortedBuildingsInView, this.#outdoors, this.#zoomState);\n\n\t\t\t\tconst floor = target ? getFloorToShow(target, this.#state.mode, this.#floorElevation) : undefined;\n\n\t\t\t\tif (floor && floor.id !== this.#mapView.currentFloor.id) {\n\t\t\t\t\tthis.#mapView.setFloor(floor, { context: 'dynamic-focus' });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tawait this.#applyBuildingStates();\n\t\t// must publish after the scene is updated to ensure the focusedFacades array is up to date\n\t\tthis.#pubsub.publish('focus', { facades: this.focusedFacades });\n\t}\n\n\t/**\n\t * Preloads the initial floors for each building to improve performance when rendering the building for the first time. See {@link DynamicFocusState.preloadFloors}.\n\t */\n\tpreloadFloors() {\n\t\tthis.#preloadFloors(this.#state.mode);\n\t}\n\n\t/**\n\t * Sets the default floor for a floor stack. This is the floor that will be shown when focusing on a facade if there is no currently active floor in the stack.\n\t * See {@link resetDefaultFloorForStack} to reset the default floor.\n\t * @param floorStack - The floor stack to set the default floor for.\n\t * @param floor - The floor to set as the default floor.\n\t */\n\tsetDefaultFloorForStack(floorStack: FloorStack, floor: Floor) {\n\t\tif (!validateFloorForStack(floor, floorStack)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst building = this.#buildings.get(floorStack.id);\n\t\tif (building) {\n\t\t\tbuilding.defaultFloor = floor;\n\t\t}\n\t}\n\n\t/**\n\t * Resets the default floor for a floor stack to it's initial value.\n\t * @param floorStack - The floor stack to reset the default floor for.\n\t */\n\tresetDefaultFloorForStack(floorStack: FloorStack) {\n\t\tconst building = this.#buildings.get(floorStack.id);\n\t\tif (building) {\n\t\t\tbuilding.defaultFloor = floorStack.defaultFloor;\n\t\t}\n\t}\n\n\t/**\n\t * Returns the current default floor for a floor stack.\n\t * @param floorStack - The floor stack to get the default floor for.\n\t * @returns The current default floor for the floor stack.\n\t */\n\tgetDefaultFloorForStack(floorStack: FloorStack) {\n\t\treturn this.#buildings.get(floorStack.id)?.defaultFloor || floorStack.defaultFloor || floorStack.floors[0];\n\t}\n\n\t/**\n\t * Sets the current floor for a floor stack. If the floor stack is currently focused, this floor will become visible.\n\t * @param floorStack - The floor stack to set the current floor for.\n\t */\n\tsetCurrentFloorForStack(floorStack: FloorStack, floor: Floor) {\n\t\tif (!validateFloorForStack(floor, floorStack)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst building = this.#buildings.get(floorStack.id);\n\t\tif (building) {\n\t\t\tbuilding.activeFloor = floor;\n\t\t\tthis.#applyBuildingStates();\n\t\t}\n\t}\n\n\t/**\n\t * Excludes a floor stack from visibility changes.\n\t * @param excluded - The floor stack or stacks to exclude.\n\t */\n\texclude(excluded: FloorStack | FloorStack[]) {\n\t\tconst excludedFloorStacks = Array.isArray(excluded) ? excluded : [excluded];\n\t\tfor (const floorStack of excludedFloorStacks) {\n\t\t\tconst building = this.#buildings.get(floorStack.id);\n\t\t\tif (building) {\n\t\t\t\tbuilding.excluded = true;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Includes a floor stack in visibility changes.\n\t * @param included - The floor stack or stacks to include.\n\t */\n\tinclude(included: FloorStack | FloorStack[]) {\n\t\tconst includedFloorStacks = Array.isArray(included) ? included : [included];\n\t\tfor (const floorStack of includedFloorStacks) {\n\t\t\tconst building = this.#buildings.get(floorStack.id);\n\t\t\tif (building) {\n\t\t\t\tbuilding.excluded = false;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Returns the current floor for a floor stack.\n\t * @param floorStack - The floor stack to get the current floor for.\n\t * @returns The current floor for the floor stack.\n\t */\n\tgetCurrentFloorForStack(floorStack: FloorStack) {\n\t\treturn this.#buildings.get(floorStack.id)?.activeFloor || this.getDefaultFloorForStack(floorStack);\n\t}\n\n\t/**\n\t * Handles management of focused facades but doesn't trigger view updates unless enabled.\n\t * @see {@link focus} to manually trigger a view update.\n\t */\n\t#handleFacadesInViewChange = (event: TEvents['facades-in-view-change']) => {\n\t\tif (!this.isEnabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { facades } = event;\n\n\t\t// if the facades are the same, or we're in between outdoor/indoor, don't do anything unless we're pending a facade update\n\t\tif (arraysEqual(facades, this.focusedFacades) && this.#viewState === 'transition' && !this.#pendingFacadeUpdate) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#pendingFacadeUpdate = false;\n\n\t\tthis.#sortedBuildingsInView = [];\n\t\tthis.#buildingIdsInViewSet.clear();\n\t\tif (facades.length > 0) {\n\t\t\tfor (const facade of facades) {\n\t\t\t\tconst building = this.#buildings.get(facade.floorStack.id);\n\t\t\t\tif (building) {\n\t\t\t\t\tthis.#buildingIdsInViewSet.add(building.id);\n\t\t\t\t\tthis.#sortedBuildingsInView.push(building);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.#state.autoFocus) {\n\t\t\tthis.focus();\n\t\t}\n\t};\n\t/**\n\t * Handles floor and facade visibility when the floor changes.\n\t */\n\t#handleFloorChangeStart = async (event: TEvents['floor-change-start']) => {\n\t\tif (!this.isEnabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { floor: newFloor } = event;\n\t\tconst building = this.#buildings.get(newFloor.floorStack.id);\n\t\tif (building) {\n\t\t\tbuilding.activeFloor = newFloor;\n\t\t}\n\t\t// Don't update elevation when switching to outdoor floor stack\n\t\tif (building?.excluded === false && !this.#outdoors.matchesFloorStack(newFloor.floorStack)) {\n\t\t\tthis.#floorElevation = newFloor.elevation;\n\t\t}\n\n\t\tif (this.#mapView.manualFloorVisibility === true) {\n\t\t\tif (event.reason !== 'dynamic-focus') {\n\t\t\t\tawait this.#applyBuildingStates(newFloor);\n\t\t\t\t// Despite this not really being a focus event, we've changed the focused facades, so we need to publish it\n\t\t\t\tthis.#pubsub.publish('focus', { facades: this.focusedFacades });\n\t\t\t}\n\n\t\t\tconst altitude = building?.floorsAltitudesMap.get(newFloor.elevation)?.altitude ?? 0;\n\t\t\tif (\n\t\t\t\tthis.#mapView.options.multiFloorView != null &&\n\t\t\t\tthis.#mapView.options.multiFloorView?.enabled &&\n\t\t\t\tthis.#mapView.options.multiFloorView?.updateCameraElevationOnFloorChange &&\n\t\t\t\tthis.#mapView.Camera.elevation !== altitude\n\t\t\t) {\n\t\t\t\tthis.#mapView.Camera.animateElevation(altitude, {\n\t\t\t\t\tduration: 750,\n\t\t\t\t\teasing: 'ease-in-out',\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t};\n\n\t#handleUserInteractionStart = () => {\n\t\tthis.#userInteracting = true;\n\t};\n\t#handleUserInteractionEnd = () => {\n\t\tthis.#userInteracting = false;\n\t};\n\n\t/**\n\t * Handles camera moving in and out of zoom range and fires a focus event if the camera is in range.\n\t */\n\t#handleCameraChange = (event: TEvents['camera-change']) => {\n\t\tif (!this.isEnabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { zoomLevel } = event;\n\t\tconst newZoomState = getZoomState(zoomLevel, this.#state.indoorZoomThreshold, this.#state.outdoorZoomThreshold);\n\n\t\tif (this.#zoomState !== newZoomState) {\n\t\t\tthis.#zoomState = newZoomState;\n\n\t\t\tif (newZoomState === 'in-range') {\n\t\t\t\tthis.setIndoor();\n\t\t\t} else if (newZoomState === 'out-of-range') {\n\t\t\t\tthis.setOutdoor();\n\t\t\t}\n\t\t}\n\t};\n\n\t#updateFloorVisibility(floorStates: BuildingFloorStackState['floorStates'], shouldShow: boolean, inFocus?: boolean) {\n\t\tfloorStates.forEach(floorState => {\n\t\t\tif (floorState.floor) {\n\t\t\t\tif (shouldShow) {\n\t\t\t\t\tconst state =\n\t\t\t\t\t\tinFocus !== undefined\n\t\t\t\t\t\t\t? ({\n\t\t\t\t\t\t\t\t\t...floorState.state,\n\t\t\t\t\t\t\t\t\tlabels: {\n\t\t\t\t\t\t\t\t\t\t...floorState.state.labels,\n\t\t\t\t\t\t\t\t\t\tenabled: floorState.state.labels.enabled && inFocus,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tmarkers: {\n\t\t\t\t\t\t\t\t\t\t...floorState.state.markers,\n\t\t\t\t\t\t\t\t\t\tenabled: floorState.state.markers.enabled && inFocus,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tocclusion: {\n\t\t\t\t\t\t\t\t\t\t...floorState.state.occlusion,\n\t\t\t\t\t\t\t\t\t\t// We don't want this floor to occlude if it's not in focus\n\t\t\t\t\t\t\t\t\t\t// Allows us to show a label above this floor while it's not active\n\t\t\t\t\t\t\t\t\t\tenabled: floorState.state.occlusion.enabled && inFocus,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t } satisfies TFloorState)\n\t\t\t\t\t\t\t: floorState.state;\n\n\t\t\t\t\tthis.#mapView.updateState(floorState.floor, state);\n\t\t\t\t} else {\n\t\t\t\t\tthis.#mapView.updateState(floorState.floor, { visible: false });\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tasync #animateIndoorSequence(\n\t\tbuilding: Building,\n\t\tfloorStackState: BuildingFloorStackState,\n\t\tfacadeState: BuildingFacadeState,\n\t\tinFocus: boolean,\n\t) {\n\t\t// show floor first then fade in the facade\n\t\tthis.#updateFloorVisibility(floorStackState.floorStates, true, inFocus);\n\n\t\treturn building.animateFacade(facadeState.state, this.#state.indoorAnimationOptions);\n\t}\n\n\tasync #animateOutdoorSequence(\n\t\tbuilding: Building,\n\t\tfloorStackState: BuildingFloorStackState,\n\t\tfacadeState: BuildingFacadeState,\n\t\tfloorStackIdsInNavigation: string[],\n\t) {\n\t\t// fade in facade then hide floors when complete\n\t\tconst result = await building.animateFacade(facadeState.state, this.#state.outdoorAnimationOptions);\n\n\t\tif (result.result === 'completed') {\n\t\t\t// Re-check if we should still show indoor after animation completes\n\t\t\tthis.#updateFloorVisibility(\n\t\t\t\tfloorStackState.floorStates,\n\t\t\t\tshouldShowIndoor(\n\t\t\t\t\tbuilding,\n\t\t\t\t\tthis.#mapView.currentFloor,\n\t\t\t\t\tthis.#zoomState === 'in-range',\n\t\t\t\t\tthis.#buildingIdsInViewSet.has(building.id),\n\t\t\t\t\tthis.#state.mode,\n\t\t\t\t\tthis.#floorElevation,\n\t\t\t\t\tfloorStackIdsInNavigation.includes(building.floorStack.id),\n\t\t\t\t\tthis.#state.dynamicBuildingInteriors,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t#applyBuildingStates = async (newFloor?: Floor) => {\n\t\tif (this.#mapView.manualFloorVisibility !== true || !this.isEnabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentFloor = newFloor || this.#mapView.currentFloor;\n\t\tconst multiFloorView = this.#mapView.options.multiFloorView;\n\t\tconst floorIdsInNavigation = this.#mapView.Navigation?.floors?.map(f => f.id) || [];\n\t\tconst floorStackIdsInNavigation = this.#mapView.Navigation?.floorStacks.map(fs => fs.id) || [];\n\n\t\t// Create a new promise for this update\n\t\tconst updatePromise = new Promise<void>(async resolve => {\n\t\t\t// Wait for the previous update to complete\n\t\t\tawait this.sceneUpdateQueue;\n\n\t\t\tconst buildingStates = getBuildingStates(\n\t\t\t\tArray.from(this.#buildings.values()),\n\t\t\t\tthis.#buildingIdsInViewSet,\n\t\t\t\tcurrentFloor,\n\t\t\t\tthis.#zoomState,\n\t\t\t\tthis.#state.mode,\n\t\t\t\tthis.#floorElevation,\n\t\t\t\tfloorIdsInNavigation,\n\t\t\t\tfloorStackIdsInNavigation,\n\t\t\t\tmultiFloorView,\n\t\t\t\tthis.#state.customMultiFloorVisibilityState ?? getMultiFloorState,\n\t\t\t\tthis.#state.dynamicBuildingInteriors,\n\t\t\t);\n\n\t\t\tconst floorStackStates: BuildingFloorStackState[] = [];\n\t\t\tawait Promise.all(\n\t\t\t\tArray.from(buildingStates.values()).map(async buildingState => {\n\t\t\t\t\tconst { building, showIndoor, floorStackState, facadeState, inFocus } = buildingState;\n\n\t\t\t\t\tfloorStackStates.push(floorStackState);\n\n\t\t\t\t\tconst animation = getBuildingAnimationType(building, showIndoor);\n\n\t\t\t\t\tif (animation === 'indoor') {\n\t\t\t\t\t\treturn this.#animateIndoorSequence(building, floorStackState, facadeState, inFocus);\n\t\t\t\t\t} else if (animation === 'outdoor') {\n\t\t\t\t\t\treturn this.#animateOutdoorSequence(building, floorStackState, facadeState, floorStackIdsInNavigation);\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t);\n\n\t\t\tthis.#mapView.Outdoor.setOpacity(getOutdoorOpacity(floorStackStates, this.#state.mode));\n\n\t\t\t// Filter #facadesInFocus to maintain sort order, keeping only buildings with showIndoor true\n\t\t\tthis.#facadesInFocus = this.#sortedBuildingsInView\n\t\t\t\t.filter(building => buildingStates.get(building.id)?.showIndoor === true)\n\t\t\t\t.map(building => building.facade);\n\n\t\t\tthis.#pubsub.publish('focus', { facades: this.#facadesInFocus });\n\n\t\t\tresolve();\n\t\t});\n\n\t\t// Update the queue with the new promise\n\t\tthis.sceneUpdateQueue = updatePromise;\n\n\t\treturn updatePromise;\n\t};\n}\n", "/**\n * Compare two arrays for equality\n */\nexport function arraysEqual(arr1: any[] | null | undefined, arr2: any[] | null | undefined) {\n\tif (arr1 == null || arr2 == null) {\n\t\treturn arr1 === arr2;\n\t}\n\n\tif (arr1.length !== arr2.length) {\n\t\treturn false;\n\t}\n\n\tfor (let i = 0; i < arr1.length; i++) {\n\t\tif (arr1[i] !== arr2[i]) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n", "/**\n * Generic PubSub class implementing the Publish-Subscribe pattern for event handling.\n *\n * @template EVENT_PAYLOAD - The type of the event payload.\n * @template EVENT - The type of the event.\n */\nexport class PubSub<EVENT_PAYLOAD, EVENT extends keyof EVENT_PAYLOAD = keyof EVENT_PAYLOAD> {\n\t/**\n\t * @private\n\t * @internal\n\t */\n\tprivate _subscribers: any = {};\n\t/**\n\t * @private\n\t * @internal\n\t */\n\tprivate _destroyed = false;\n\n\t/**\n\t * @private\n\t * @internal\n\t */\n\tpublish<EVENT_NAME extends EVENT>(eventName: EVENT_NAME, data?: EVENT_PAYLOAD[EVENT_NAME]) {\n\t\tif (!this._subscribers || !this._subscribers[eventName] || this._destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._subscribers[eventName]!.forEach(function (fn) {\n\t\t\tif (typeof fn !== 'function') {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfn(data);\n\t\t});\n\t}\n\n\t/**\n\t * Subscribe a function to an event.\n\t *\n\t * @param eventName An event name which, when fired, will call the provided\n\t * function.\n\t * @param fn A callback that gets called when the corresponding event is fired. The\n\t * callback will get passed an argument with a type that's one of event payloads.\n\t * @example\n\t * // Subscribe to the 'click' event\n\t * const handler = (event) => {\n\t * const { coordinate } = event;\n\t * const { latitude, longitude } = coordinate;\n\t * \tconsole.log(`Map was clicked at ${latitude}, ${longitude}`);\n\t * };\n\t * map.on('click', handler);\n\t */\n\ton<EVENT_NAME extends EVENT>(\n\t\teventName: EVENT_NAME,\n\t\tfn: (\n\t\t\tpayload: EVENT_PAYLOAD[EVENT_NAME] extends {\n\t\t\t\tdata: null;\n\t\t\t}\n\t\t\t\t? EVENT_PAYLOAD[EVENT_NAME]['data']\n\t\t\t\t: EVENT_PAYLOAD[EVENT_NAME],\n\t\t) => void,\n\t) {\n\t\tif (!this._subscribers || this._destroyed) {\n\t\t\tthis._subscribers = {};\n\t\t}\n\t\tthis._subscribers[eventName] = this._subscribers[eventName] || [];\n\t\tthis._subscribers[eventName]!.push(fn);\n\t}\n\n\t/**\n\t * Unsubscribe a function previously subscribed with {@link on}\n\t *\n\t * @param eventName An event name to which the provided function was previously\n\t * subscribed.\n\t * @param fn A function that was previously passed to {@link on}. The function must\n\t * have the same reference as the function that was subscribed.\n\t * @example\n\t * // Unsubscribe from the 'click' event\n\t * const handler = (event) => {\n\t * \tconsole.log('Map was clicked', event);\n\t * };\n\t * map.off('click', handler);\n\t */\n\toff<EVENT_NAME extends EVENT>(\n\t\teventName: EVENT_NAME,\n\t\tfn: (\n\t\t\tpayload: EVENT_PAYLOAD[EVENT_NAME] extends {\n\t\t\t\tdata: null;\n\t\t\t}\n\t\t\t\t? EVENT_PAYLOAD[EVENT_NAME]['data']\n\t\t\t\t: EVENT_PAYLOAD[EVENT_NAME],\n\t\t) => void,\n\t) {\n\t\tif (!this._subscribers || this._subscribers[eventName] == null || this._destroyed) {\n\t\t\treturn;\n\t\t}\n\t\tconst itemIdx = this._subscribers[eventName]!.indexOf(fn);\n\n\t\tif (itemIdx !== -1) {\n\t\t\tthis._subscribers[eventName]!.splice(itemIdx, 1);\n\t\t}\n\t}\n\t/**\n\t * @private\n\t * @internal\n\t */\n\tdestroy() {\n\t\tthis._destroyed = true;\n\t\tthis._subscribers = {};\n\t}\n}\n", "import type { MapView, TAnimateStateResult, TFacadeState } from '@mappedin/mappedin-js';\nimport { Facade, Floor, FloorStack } from '@mappedin/mappedin-js';\nimport type { DynamicFocusAnimationOptions } from './types';\n\nexport class Building {\n\t__type = 'building';\n\t#floorStack: FloorStack;\n\t#floorsById = new Map<string, Floor>();\n\t#floorsByElevation = new Map<number, Floor>();\n\t#floorsByElevationSorted: Floor[] = [];\n\t#mapView: MapView;\n\t#animationInProgress: { state: TFacadeState; animation: ReturnType<MapView['animateState']> } | undefined;\n\n\tdefaultFloor: Floor;\n\tactiveFloor: Floor;\n\texcluded = false;\n\tfloorsAltitudesMap: Map<number, { altitude: number; effectiveHeight: number }> = new Map();\n\taboveGroundFloors: Floor[] = [];\n\n\tconstructor(floorStack: FloorStack, mapView: MapView) {\n\t\tthis.#floorStack = floorStack;\n\t\tthis.#floorsById = new Map(floorStack.floors.map(floor => [floor.id, floor]));\n\t\tthis.#floorsByElevation = new Map(floorStack.floors.map(floor => [floor.elevation, floor]));\n\t\tthis.#floorsByElevationSorted = Array.from(this.#floorsByElevation.values()).sort(\n\t\t\t(a, b) => a.elevation - b.elevation,\n\t\t);\n\t\tthis.defaultFloor = floorStack.defaultFloor;\n\t\tthis.activeFloor = this.defaultFloor;\n\t\tthis.#mapView = mapView;\n\t\tthis.aboveGroundFloors = this.#floorsByElevationSorted.filter(floor => floor.elevation >= 0);\n\n\t\tconst sortedSpaces = floorStack.facade?.spaces\n\t\t\t.map(space => this.#mapView.getState(space))\n\t\t\t.sort((a, b) => a.altitude - b.altitude);\n\t\tif (sortedSpaces && sortedSpaces.length === this.aboveGroundFloors.length) {\n\t\t\tfor (const idx in this.aboveGroundFloors) {\n\t\t\t\tconst floor = this.aboveGroundFloors[idx];\n\t\t\t\tconst space = sortedSpaces[idx];\n\t\t\t\tthis.floorsAltitudesMap.set(floor.elevation, {\n\t\t\t\t\taltitude: space.altitude,\n\t\t\t\t\teffectiveHeight: space.height,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tget id() {\n\t\treturn this.#floorStack.id;\n\t}\n\n\tget name() {\n\t\treturn this.#floorStack.name;\n\t}\n\n\tget floors() {\n\t\treturn this.#floorStack.floors;\n\t}\n\n\tget floorStack() {\n\t\treturn this.#floorStack;\n\t}\n\n\tget facade() {\n\t\t// the floorstack must have a facade if we created a building for it\n\t\treturn this.#floorStack.facade!;\n\t}\n\n\tget isCurrentFloorStack() {\n\t\treturn this.id === this.#mapView.currentFloorStack.id;\n\t}\n\n\tget isIndoor() {\n\t\tconst state = this.#mapView.getState(this.facade);\n\n\t\treturn this.isCurrentFloorStack || (state?.visible === false && state?.opacity === 0);\n\t}\n\n\tget canSetFloor() {\n\t\treturn this.isIndoor || !this.excluded;\n\t}\n\n\t#maxElevation: number | undefined;\n\tget maxElevation() {\n\t\tif (this.#maxElevation == null) {\n\t\t\tthis.#maxElevation = Math.max(...this.#floorsByElevation.keys());\n\t\t}\n\n\t\treturn this.#maxElevation;\n\t}\n\n\t#minElevation: number | undefined;\n\tget minElevation() {\n\t\tif (this.#minElevation == null) {\n\t\t\tthis.#minElevation = Math.min(...this.#floorsByElevation.keys());\n\t\t}\n\n\t\treturn this.#minElevation;\n\t}\n\n\thas(f: Floor | FloorStack | Facade) {\n\t\tif (Floor.is(f)) {\n\t\t\treturn this.#floorsById.has(f.id);\n\t\t}\n\n\t\tif (FloorStack.is(f)) {\n\t\t\treturn f.id === this.#floorStack.id;\n\t\t}\n\n\t\tif (Facade.is(f)) {\n\t\t\treturn f.id === this.facade.id;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tgetFloorByElevation(elevation: number) {\n\t\treturn this.#floorsByElevation.get(elevation);\n\t}\n\n\tgetNearestFloorByElevation(targetElevation: number): Floor | undefined {\n\t\tconst exactMatch = this.getFloorByElevation(targetElevation);\n\t\tif (exactMatch) {\n\t\t\treturn exactMatch;\n\t\t}\n\n\t\tif (targetElevation >= 0) {\n\t\t\t// For positive elevations, return highest floor if target is above max\n\t\t\tif (targetElevation > this.maxElevation) {\n\t\t\t\treturn this.#floorsByElevationSorted[this.#floorsByElevationSorted.length - 1];\n\t\t\t}\n\n\t\t\t// Search backwards from the end\n\t\t\tfor (let i = this.#floorsByElevationSorted.length - 1; i >= 0; i--) {\n\t\t\t\tconst floor = this.#floorsByElevationSorted[i];\n\t\t\t\tif (floor.elevation <= targetElevation) {\n\t\t\t\t\treturn floor;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// For negative elevations (basements), return the lowest floor if target is below min\n\t\t\tif (targetElevation < this.minElevation) {\n\t\t\t\treturn this.#floorsByElevationSorted[0];\n\t\t\t}\n\n\t\t\t// Search forwards from the start\n\t\t\tfor (const floor of this.#floorsByElevationSorted) {\n\t\t\t\tif (floor.elevation >= targetElevation) {\n\t\t\t\t\treturn floor;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\tgetHighestFloor(): Floor {\n\t\treturn this.#floorsByElevationSorted[this.#floorsByElevationSorted.length - 1];\n\t}\n\n\tcancelAnimation() {\n\t\tif (this.#animationInProgress) {\n\t\t\tthis.#animationInProgress.animation.cancel();\n\t\t\tthis.#animationInProgress = undefined;\n\t\t}\n\t}\n\n\tasync animateFacade(\n\t\tnewState: TFacadeState,\n\t\toptions: DynamicFocusAnimationOptions = { duration: 150 },\n\t): Promise<TAnimateStateResult> {\n\t\tconst currentState = this.#animationInProgress?.state || this.#mapView.getState(this.facade);\n\t\tif (\n\t\t\t!currentState ||\n\t\t\t!newState ||\n\t\t\t(currentState?.opacity === newState.opacity && currentState?.visible === newState.visible)\n\t\t) {\n\t\t\t// nothing to do\n\t\t\treturn { result: 'completed' };\n\t\t}\n\n\t\tthis.cancelAnimation();\n\t\tconst { opacity, visible } = newState;\n\n\t\t// always set facade visible so it can be seen during animation\n\t\tthis.#mapView.updateState(this.facade, {\n\t\t\tvisible: true,\n\t\t});\n\n\t\tif (opacity !== undefined) {\n\t\t\tthis.#animationInProgress = {\n\t\t\t\tanimation: this.#mapView.animateState(\n\t\t\t\t\tthis.facade,\n\t\t\t\t\t{\n\t\t\t\t\t\topacity,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tduration: options.duration,\n\t\t\t\t\t},\n\t\t\t\t),\n\t\t\t\tstate: newState,\n\t\t\t};\n\t\t\tconst result = await this.#animationInProgress.animation;\n\n\t\t\tthis.#animationInProgress = undefined;\n\n\t\t\tif (result.result === 'cancelled') {\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\n\t\tif (visible === false) {\n\t\t\tthis.#mapView.updateState(this.facade, {\n\t\t\t\tvisible,\n\t\t\t});\n\t\t}\n\n\t\treturn { result: 'completed' };\n\t}\n\n\tdestroy() {\n\t\tthis.cancelAnimation();\n\t\t// Hide all floors except current floor\n\t\tthis.#floorStack.floors.forEach(floor => {\n\t\t\tthis.#mapView.updateState(floor, {\n\t\t\t\tvisible: floor.id === this.#mapView.currentFloor.id,\n\t\t\t});\n\t\t});\n\t\t// Show the facade if the current floor is not in this building\n\t\tif (!this.has(this.#mapView.currentFloor)) {\n\t\t\tthis.#mapView.updateState(this.facade, {\n\t\t\t\tvisible: true,\n\t\t\t\topacity: 1,\n\t\t\t});\n\t\t}\n\t}\n}\n", "import type { Facade, Floor, FloorStack, TFloorState } from '@mappedin/mappedin-js';\nimport type { Building } from './building';\nimport type {\n\tBuildingAnimation,\n\tBuildingFacadeState,\n\tBuildingFloorStackState,\n\tDynamicFocusMode,\n\tMultiFloorVisibilityState,\n\tZoomState,\n} from './types';\nimport type { Outdoors } from './outdoors';\n\n/**\n * Calculates the zoom state based on camera zoom level and thresholds.\n */\nexport function getZoomState(zoomLevel: number, indoorThreshold: number, outdoorThreshold: number): ZoomState {\n\tif (zoomLevel >= indoorThreshold) {\n\t\treturn 'in-range';\n\t}\n\tif (zoomLevel <= outdoorThreshold) {\n\t\treturn 'out-of-range';\n\t}\n\n\treturn 'transition';\n}\n\nexport function getFloorToShow(\n\ttarget: Building | Outdoors,\n\tmode: DynamicFocusMode,\n\televation: number,\n): Floor | undefined {\n\tif (target.__type === 'outdoors' && 'floor' in target) {\n\t\treturn target.floor;\n\t}\n\n\tconst building = target as Building;\n\tif (building.excluded) {\n\t\treturn building.activeFloor;\n\t}\n\n\tswitch (mode) {\n\t\tcase 'lock-elevation':\n\t\t\treturn building.getFloorByElevation(elevation);\n\t\tcase 'nearest-elevation':\n\t\t\treturn building.getNearestFloorByElevation(elevation);\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\t// if the building is already showing, don't switch to the default floor\n\treturn building.isIndoor ? building.activeFloor : building.defaultFloor;\n}\n\nexport function getFacadeState(facade: Facade, inFocus: boolean): BuildingFacadeState {\n\treturn {\n\t\tfacade,\n\t\tstate: {\n\t\t\ttype: 'facade',\n\t\t\tvisible: !inFocus,\n\t\t\topacity: inFocus ? 0 : 1,\n\t\t},\n\t};\n}\n\nexport function getSingleBuildingState(\n\tfloorStack: FloorStack,\n\tcurrentFloor: Floor,\n\tinFocus: boolean,\n): BuildingFloorStackState {\n\treturn {\n\t\toutdoorOpacity: 1,\n\t\tfloorStates: floorStack.floors.map(f => {\n\t\t\tconst visible = f.id === currentFloor.id && inFocus;\n\n\t\t\treturn {\n\t\t\t\tfloor: f,\n\t\t\t\tstate: {\n\t\t\t\t\ttype: 'floor',\n\t\t\t\t\tvisible: visible,\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\tvisible: visible,\n\t\t\t\t\t},\n\t\t\t\t\tlabels: {\n\t\t\t\t\t\tenabled: visible,\n\t\t\t\t\t},\n\t\t\t\t\tmarkers: {\n\t\t\t\t\t\tenabled: visible,\n\t\t\t\t\t},\n\t\t\t\t\tfootprint: {\n\t\t\t\t\t\tvisible: false,\n\t\t\t\t\t},\n\t\t\t\t\tocclusion: {\n\t\t\t\t\t\tenabled: false,\n\t\t\t\t\t},\n\t\t\t\t} as Required<TFloorState>,\n\t\t\t};\n\t\t}),\n\t};\n}\n\n/**\n * Calculates the outdoor opacity based on floor stack states and mode.\n */\nexport function getOutdoorOpacity(floorStackStates: BuildingFloorStackState[], mode: DynamicFocusMode): number {\n\tif (!mode.includes('lock-elevation')) {\n\t\treturn 1;\n\t}\n\n\tfor (const state of floorStackStates) {\n\t\tif (state.outdoorOpacity >= 0 && state.outdoorOpacity <= 1) {\n\t\t\treturn state.outdoorOpacity;\n\t\t}\n\t}\n\n\treturn 1;\n}\n\nexport function getSetFloorTargetFromZoomState(\n\tbuildings: Building[],\n\toutdoors: Outdoors,\n\tzoomState: ZoomState,\n): Building | Outdoors | undefined {\n\tswitch (zoomState) {\n\t\tcase 'in-range':\n\t\t\treturn buildings[0]?.canSetFloor ? buildings[0] : undefined;\n\t\tcase 'out-of-range':\n\t\t\treturn outdoors;\n\t\tcase 'transition':\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n}\n\n/**\n * Gets the building states for all buildings.\n */\nexport function getBuildingStates(\n\tbuildings: Building[],\n\tinViewSet: Set<string>,\n\tcurrentFloor: Floor,\n\tzoomState: ZoomState,\n\tmode: DynamicFocusMode,\n\televation: number,\n\tfloorIdsInNavigation: string[],\n\tfloorStackIdsInNavigation: string[],\n\tmultiFloorView: any,\n\tgetMultiFloorState: MultiFloorVisibilityState,\n\tdynamicBuildingInteriors: boolean,\n): Map<\n\tstring,\n\t{\n\t\tbuilding: Building;\n\t\tshowIndoor: boolean;\n\t\tfloorStackState: BuildingFloorStackState;\n\t\tfacadeState: BuildingFacadeState;\n\t\tinFocus: boolean;\n\t\tfloorToShow: Floor | undefined;\n\t}\n> {\n\tconst buildingStates = new Map();\n\n\tfor (const building of buildings) {\n\t\tconst inCameraView = inViewSet.has(building.id);\n\t\tconst showIndoor = shouldShowIndoor(\n\t\t\tbuilding,\n\t\t\tcurrentFloor,\n\t\t\tzoomState === 'in-range',\n\t\t\tinCameraView,\n\t\t\tmode,\n\t\t\televation,\n\t\t\tfloorStackIdsInNavigation.includes(building.id),\n\t\t\tdynamicBuildingInteriors,\n\t\t);\n\n\t\tconst floorToShow =\n\t\t\tcurrentFloor.floorStack.id === building.id ? building.activeFloor : getFloorToShow(building, mode, elevation);\n\n\t\tconst floorStackState = multiFloorView.enabled\n\t\t\t? getMultiFloorState(\n\t\t\t\t\tbuilding.floors,\n\t\t\t\t\tfloorToShow || building.activeFloor,\n\t\t\t\t\tmultiFloorView?.floorGap,\n\t\t\t\t\tfloorIdsInNavigation,\n\t\t\t\t\tbuilding.floorsAltitudesMap,\n\t\t\t )\n\t\t\t: getSingleBuildingState(building.floorStack, floorToShow || building.activeFloor, showIndoor);\n\n\t\tconst facadeState = getFacadeState(building.facade, showIndoor);\n\t\tbuildingStates.set(building.id, {\n\t\t\tbuilding,\n\t\t\tshowIndoor,\n\t\t\tfloorStackState,\n\t\t\tfacadeState,\n\t\t\tinFocus: inCameraView,\n\t\t\tfloorToShow,\n\t\t});\n\t}\n\n\treturn buildingStates;\n}\n\nexport function getBuildingAnimationType(building: Building, showIndoor: boolean): BuildingAnimation {\n\tif (building.excluded) {\n\t\treturn 'none';\n\t}\n\n\tif (showIndoor) {\n\t\treturn 'indoor';\n\t}\n\n\treturn 'outdoor';\n}\n\n/**\n * Determines if a building's indoor floors should be shown through a number of different state checks.\n */\nexport function shouldShowIndoor(\n\tbuilding: Building,\n\tcurrentFloor: Floor,\n\tinRange: boolean,\n\tinFocus: boolean,\n\tmode: DynamicFocusMode,\n\televation: number,\n\tinNavigation: boolean,\n\tdynamicBuildingInteriors: boolean,\n): boolean {\n\t// always show the current floor regardless of any other states\n\tif (building.id === currentFloor.floorStack.id) {\n\t\treturn true;\n\t}\n\n\t// if the building is excluded, we don't control the visibility, so don't show it\n\tif (building.excluded) {\n\t\treturn false;\n\t}\n\n\t// if it's not excluded, always show the navigation\n\tif (inNavigation === true) {\n\t\treturn true;\n\t}\n\n\t// Without dynamic building interiors, we only rely on whether the current floor is indoor or outdoor\n\tif (!dynamicBuildingInteriors) {\n\t\treturn currentFloor.floorStack.type !== 'Outdoor';\n\t}\n\n\t// the following cases rely on the camera being in range\n\tif (!inRange) {\n\t\treturn false;\n\t}\n\n\t// the following cases rely on the building being in focus\n\tif (!inFocus) {\n\t\treturn false;\n\t}\n\n\tswitch (mode) {\n\t\tcase 'lock-elevation':\n\t\t\treturn building.getFloorByElevation(elevation) != null;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\treturn true;\n}\n\nexport function shouldDeferSetFloor(\n\ttrackedCameraElevation: number,\n\tcurrentCameraElevation: number,\n\tuserInteracting: boolean,\n): boolean {\n\treturn trackedCameraElevation !== currentCameraElevation && !userInteracting;\n}\n", "import type { Facade, Floor, TFacadeState } from '@mappedin/mappedin-js';\nimport type { VisibilityState as BuildingFloorStackState } from '../../mappedin-js/src/api-geojson/multi-floor';\n\nexport type MultiFloorVisibilityState = (\n\tfloors: Floor[],\n\tcurrentFloor: Floor,\n\tfloorGap: number,\n\tfloorIdsInNavigation: Floor['id'][],\n\tfloorsVisualHeightMap?: Map<number, { altitude: number; effectiveHeight: number }>,\n) => BuildingFloorStackState;\n\nexport type DynamicFocusAnimationOptions = {\n\t/**\n\t * The duration of the animation in milliseconds.\n\t * @default 150\n\t */\n\tduration: number;\n};\n\n/**\n * Array of valid dynamic focus modes for runtime validation.\n */\nexport const DYNAMIC_FOCUS_MODES = ['default-floor', 'lock-elevation', 'nearest-elevation'] as const;\n\n/**\n * The mode which determines the indoor floor to reveal when the camera focuses on a facade.\n * - 'default-floor' - Show the default floor of the floor stack.\n * - 'lock-elevation' - Show the floor at the current elevation, if possible.\n * When a floor stack does not have a floor at the current elevation, no indoor floor will be shown.\n * - 'nearest-elevation' - Show the floor at the current elevation, if possible.\n * When a floor stack does not have a floor at the current elevation, show the indoor floor at the nearest lower elevation.\n */\nexport type DynamicFocusMode = (typeof DYNAMIC_FOCUS_MODES)[number];\n\n/**\n * State of the Dynamic Focus controller.\n */\nexport type DynamicFocusState = {\n\t/**\n\t * Whether to automatically focus on the outdoors when the camera moves in range.\n\t * @default true\n\t */\n\tautoFocus: boolean;\n\t/**\n\t * The zoom level at which the camera will fade out the facades and fade in the indoor floors.\n\t * @default 18\n\t */\n\tindoorZoomThreshold: number;\n\t/**\n\t * The zoom level at which the camera will fade in the facades and fade out the indoor floors.\n\t * @default 17\n\t */\n\toutdoorZoomThreshold: number;\n\t/**\n\t * Whether to set the floor to the outdoors when the camera moves in range.\n\t * @default true\n\t */\n\tsetFloorOnFocus: boolean;\n\t/**\n\t * Options for the animation when fading out the facade to reveal the interior.\n\t */\n\tindoorAnimationOptions: DynamicFocusAnimationOptions;\n\t/**\n\t * Options for the animation when fading in the facade to hide the interior.\n\t */\n\toutdoorAnimationOptions: DynamicFocusAnimationOptions;\n\t/**\n\t * The mode of the Dynamic Focus controller.\n\t * @default 'default-floor'\n\t */\n\tmode: DynamicFocusMode;\n\t/**\n\t * Whether to automatically adjust facade heights to align with floor boundaries in multi-floor buildings.\n\t * @default false\n\t */\n\tautoAdjustFacadeHeights: boolean;\n\t/**\n\t * Whether to automatically hide the indoors of buildings not in or near the camera's view.\n\t * @default true\n\t */\n\tdynamicBuildingInteriors: boolean;\n\t/**\n\t * Whether to preload the geometry of the initial floors in each building. Improves performance when rendering the building for the first time.\n\t * @default true\n\t */\n\tpreloadFloors: boolean;\n\n\t/**\n\t * @experimental\n\t * @internal\n\t * A custom function to override the default floor visibility state.\n\t * This is useful for customizing the floor visibility state for a specific building.\n\t */\n\tcustomMultiFloorVisibilityState?: MultiFloorVisibilityState;\n};\n\n/**\n * Internal events emitted for updating React state.\n */\nexport type InternalDynamicFocusEvents = {\n\t'state-change': undefined;\n};\n\n/**\n * Events emitted by the Dynamic Focus controller.\n */\nexport type DynamicFocusEvents = {\n\t/**\n\t * Emitted when the Dynamic Focus controller triggers a focus update either from a camera change or manually calling `focus()`.\n\t */\n\tfocus: {\n\t\tfacades: Facade[];\n\t};\n};\n\nexport type DynamicFocusEventPayload<EventName extends keyof DynamicFocusEvents> =\n\tDynamicFocusEvents[EventName] extends { data: null }\n\t\t? DynamicFocusEvents[EventName]['data']\n\t\t: DynamicFocusEvents[EventName];\n\nexport type BuildingFacadeState = {\n\tfacade: Facade;\n\tstate: TFacadeState;\n};\n\nexport type BuildingState = BuildingFloorStackState & {\n\tfacadeState: BuildingFacadeState;\n};\n\nexport type ZoomState = 'in-range' | 'out-of-range' | 'transition';\nexport type ViewState = 'indoor' | 'outdoor' | 'transition';\n\nexport type BuildingAnimation = 'indoor' | 'outdoor' | 'none';\n\nexport type { BuildingFloorStackState };\n", "import { Floor, FloorStack } from '@mappedin/mappedin-js';\nimport { clampWithWarning } from '@packages/internal/common/math-utils';\nimport Logger from '@packages/internal/common/Mappedin.Logger';\n\n/**\n * Validates that a floor belongs to the specified floor stack.\n */\nexport function validateFloorForStack(floor: Floor, floorStack: FloorStack): boolean {\n\tif (!Floor.is(floor) || floor?.floorStack == null || !FloorStack.is(floorStack)) {\n\t\treturn false;\n\t}\n\n\tif (floor.floorStack.id !== floorStack.id) {\n\t\tLogger.warn(`Floor (${floor.id}) does not belong to floor stack (${floorStack.id}).`);\n\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n/**\n * Validates and clamps zoom threshold values.\n */\nexport function validateZoomThreshold(value: number, min: number, max: number, name: string): number {\n\treturn clampWithWarning(value, min, max, `${name} must be between ${min} and ${max}.`);\n}\n", "/* eslint-disable no-console*/\nexport const MI_DEBUG_KEY = 'mi-debug';\nexport const MI_ERROR_LABEL = '[MappedinJS]';\n\nexport enum E_SDK_LOG_LEVEL {\n\tLOG,\n\tWARN,\n\tERROR,\n\tSILENT,\n}\n\nexport function createLogger(name = '', { prefix = MI_ERROR_LABEL } = {}) {\n\tconst label = `${prefix}${name ? `-${name}` : ''}`;\n\n\tconst rnDebug = (type: 'log' | 'warn' | 'error', args: any[]) => {\n\t\tif (typeof window !== 'undefined' && (window as any).rnDebug) {\n\t\t\tconst processed = args.map(arg => {\n\t\t\t\tif (arg instanceof Error && arg.stack) {\n\t\t\t\t\treturn `${arg.message}\\n${arg.stack}`;\n\t\t\t\t}\n\n\t\t\t\treturn arg;\n\t\t\t});\n\t\t\t(window as any).rnDebug(`${name} ${type}: ${processed.join(' ')}`);\n\t\t}\n\t};\n\n\treturn {\n\t\tlogState: process.env.NODE_ENV === 'test' ? E_SDK_LOG_LEVEL.SILENT : E_SDK_LOG_LEVEL.LOG,\n\n\t\tlog(...args: any[]) {\n\t\t\tif (this.logState <= E_SDK_LOG_LEVEL.LOG) {\n\t\t\t\tconsole.log(label, ...args);\n\t\t\t\trnDebug('log', args);\n\t\t\t}\n\t\t},\n\n\t\twarn(...args: any[]) {\n\t\t\tif (this.logState <= E_SDK_LOG_LEVEL.WARN) {\n\t\t\t\tconsole.warn(label, ...args);\n\t\t\t\trnDebug('warn', args);\n\t\t\t}\n\t\t},\n\n\t\terror(...args: any[]) {\n\t\t\tif (this.logState <= E_SDK_LOG_LEVEL.ERROR) {\n\t\t\t\tconsole.error(label, ...args);\n\n\t\t\t\trnDebug('error', args);\n\t\t\t}\n\t\t},\n\n\t\t// It's a bit tricky to prepend [MappedinJs] to assert and time because of how the output is structured in the console, so it is left out for simplicity\n\t\tassert(...args: any[]) {\n\t\t\tconsole.assert(...args);\n\t\t},\n\n\t\ttime(label: string) {\n\t\t\tconsole.time(label);\n\t\t},\n\n\t\ttimeEnd(label: string) {\n\t\t\tconsole.timeEnd(label);\n\t\t},\n\t\tsetLevel(level: E_SDK_LOG_LEVEL) {\n\t\t\tif (E_SDK_LOG_LEVEL.LOG <= level && level <= E_SDK_LOG_LEVEL.SILENT) {\n\t\t\t\tthis.logState = level;\n\t\t\t}\n\t\t},\n\t};\n}\n\nconst Logger = createLogger();\nexport function setLoggerLevel(level: E_SDK_LOG_LEVEL) {\n\tif (E_SDK_LOG_LEVEL.LOG <= level && level <= E_SDK_LOG_LEVEL.SILENT) {\n\t\tLogger.logState = level;\n\t}\n}\n\nexport default Logger;\n", "import Logger from './Mappedin.Logger';\n\n/**\n * Clamp a number between lower and upper bounds with a warning\n */\nexport function clampWithWarning(x: number, lower: number, upper: number, warning: string) {\n\tif (x < lower || x > upper) {\n\t\tLogger.warn(warning);\n\t}\n\n\treturn Math.min(upper, Math.max(lower, x));\n}\n", "import { createLogger } from '../../packages/common/Mappedin.Logger';\n\nexport const Logger = createLogger('', { prefix: '[DynamicFocus]' });\n", "import type { FloorStack, MapView } from '@mappedin/mappedin-js';\nimport { Logger } from './logger';\nimport type { Building } from './building';\n\nexport class Outdoors {\n\t__type = 'outdoors';\n\t#floorStack: FloorStack;\n\t#mapView: MapView;\n\n\tconstructor(floorStack: FloorStack, mapView: MapView) {\n\t\tthis.#floorStack = floorStack;\n\t\tthis.#mapView = mapView;\n\t}\n\n\tget id() {\n\t\treturn this.#floorStack.id;\n\t}\n\n\tget floorStack() {\n\t\treturn this.#floorStack;\n\t}\n\n\tget floor() {\n\t\t// outdoors should only have 1 floor\n\t\treturn this.#floorStack.defaultFloor;\n\t}\n\n\tmatchesFloorStack(floorStack: FloorStack | string) {\n\t\treturn floorStack === this.#floorStack || floorStack === this.#floorStack.id;\n\t}\n\n\t#setVisible(visible: boolean) {\n\t\tfor (const floor of this.#floorStack.floors) {\n\t\t\tthis.#mapView.updateState(floor, {\n\t\t\t\tvisible,\n\t\t\t});\n\t\t}\n\t}\n\n\tshow() {\n\t\tthis.#setVisible(true);\n\t}\n\n\thide() {\n\t\tthis.#setVisible(false);\n\t}\n\n\tdestroy() {\n\t\tif (!this.matchesFloorStack(this.#mapView.currentFloorStack)) {\n\t\t\tthis.hide();\n\t\t}\n\t}\n}\n\nexport function getOutdoorFloorStack(floorStacks: FloorStack[], buildingsSet: Map<string, Building>): FloorStack {\n\tconst outdoorFloorStack = floorStacks.find(floorStack => floorStack.type?.toLowerCase() === 'outdoor');\n\n\tif (outdoorFloorStack) {\n\t\treturn outdoorFloorStack;\n\t}\n\n\t// If no outdoor type found, find the first floor stack that does not have a facade or is already in the buildings set\n\tconst likelyOutdoorFloorStack = floorStacks.find(\n\t\tfloorStack => floorStack.facade == null && !buildingsSet.has(floorStack.id),\n\t);\n\n\tif (likelyOutdoorFloorStack) {\n\t\treturn likelyOutdoorFloorStack;\n\t}\n\n\tLogger.warn('No good candidate for the outdoor floor stack was found. Using the first floor stack.');\n\n\treturn floorStacks[0];\n}\n", "import { getMultiFloorState } from '@mappedin/mappedin-js';\nimport type { RequiredDeep } from 'type-fest';\nimport type { DynamicFocusState } from './types';\n\nexport const DEFAULT_STATE: RequiredDeep<DynamicFocusState> = {\n\tindoorZoomThreshold: 18,\n\toutdoorZoomThreshold: 17,\n\tsetFloorOnFocus: true,\n\tautoFocus: false,\n\tindoorAnimationOptions: {\n\t\tduration: 150,\n\t},\n\toutdoorAnimationOptions: {\n\t\tduration: 150,\n\t},\n\tautoAdjustFacadeHeights: false,\n\tmode: 'default-floor',\n\tpreloadFloors: true,\n\tcustomMultiFloorVisibilityState: getMultiFloorState,\n\tdynamicBuildingInteriors: true,\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["export { DynamicFocus } from './dynamic-focus';\nexport type {\n\tDynamicFocusState,\n\tDynamicFocusMode,\n\tDynamicFocusAnimationOptions,\n\tDynamicFocusEvents,\n\tDynamicFocusEventPayload,\n} from './types';\n", "import type {\n\tCameraTransform,\n\tFacade,\n\tFloorStack,\n\tMapData,\n\tMapView,\n\tTEvents,\n\tTFloorState,\n} from '@mappedin/mappedin-js';\nimport { Floor, getMultiFloorState } from '@mappedin/mappedin-js';\nimport { arraysEqual } from '@packages/internal/common/array-utils';\nimport { PubSub } from '@packages/internal/common/pubsub';\nimport { Building } from './building';\nimport {\n\tgetFloorToShow,\n\tshouldShowIndoor,\n\tgetBuildingAnimationType,\n\tgetZoomState,\n\tgetOutdoorOpacity,\n\tgetSetFloorTargetFromZoomState,\n\tgetBuildingStates,\n\tshouldDeferSetFloor,\n} from './dynamic-focus-scene';\nimport { DYNAMIC_FOCUS_MODES } from './types';\nimport type {\n\tViewState,\n\tZoomState,\n\tBuildingFacadeState,\n\tDynamicFocusEventPayload,\n\tDynamicFocusEvents,\n\tDynamicFocusMode,\n\tDynamicFocusState,\n\tBuildingFloorStackState,\n\tInternalDynamicFocusEvents,\n} from './types';\nimport { validateFloorForStack, validateZoomThreshold } from './validation';\nimport { getOutdoorFloorStack, Outdoors } from './outdoors';\nimport { Logger } from './logger';\nimport MappedinJSLogger from '../../packages/common/Mappedin.Logger';\nimport { DEFAULT_STATE } from './constants';\nimport type { MapViewExtension } from '@packages/internal/common/extensions';\n\n/**\n * Dynamic Focus is a MapView scene manager that maintains the visibility of the outdoors\n * while fading in and out building interiors as the camera pans.\n */\nexport class DynamicFocus implements MapViewExtension<DynamicFocusState> {\n\t#pubsub: PubSub<DynamicFocusEvents & InternalDynamicFocusEvents>;\n\t#mapView: MapView;\n\t#mapData: MapData;\n\t#state: Required<DynamicFocusState> = DEFAULT_STATE;\n\t/**\n\t * The buildings that are currently in view, sorted by the order they are in the facades-in-view-change event.\n\t * While these will be within the camera view, these may not be in focus or showIndoor depending on the mode.\n\t */\n\t#sortedBuildingsInView: Building[] = [];\n\t/**\n\t * The buildings that are currently in view, as a set of building ids.\n\t */\n\t#buildingIdsInViewSet = new Set<string>();\n\t#buildings = new Map<string, Building>();\n\t#outdoors: Outdoors;\n\t#userInteracting = false;\n\t#pendingFacadeUpdate = false;\n\t#floorElevation = 0;\n\t#cameraElevation = 0;\n\t/**\n\t * Tracks the current zoom state based on camera zoom level:\n\t * - 'in-range': Camera is zoomed in enough to show indoor details (>= indoorZoomThreshold)\n\t * - 'out-of-range': Camera is zoomed out to show outdoor context (<= outdoorZoomThreshold)\n\t * - 'transition': Camera is between the two thresholds (no floor changes occur)\n\t */\n\t#zoomState: ZoomState = 'transition';\n\t#viewState: ViewState = 'outdoor';\n\t/**\n\t * The facades that are actually focused and shown (filtered by showIndoor logic)\n\t */\n\t#facadesInFocus: Facade[] = [];\n\t#enabled = false;\n\n\t/**\n\t * @internal\n\t * Used to await the current scene update before starting a new one, or when the scene is updated asynchronously by an event.\n\t */\n\tprivate sceneUpdateQueue: Promise<void> = Promise.resolve();\n\n\t/**\n\t * Creates a new instance of the Dynamic Focus controller.\n\t *\n\t * @param mapView - The {@link MapView} to attach Dynamic Focus to.\n\t * @param options - Options for configuring Dynamic Focus.\n\t *\n\t * @example\n\t * ```ts\n\t * const mapView = show3dMap(...);\n\t * const df = new DynamicFocus(mapView);\n\t * df.enable({ autoFocus: true });\n\t *\n\t * // pause the listener\n\t * df.updateState({ autoFocus: false });\n\t *\n\t * // manually trigger a focus\n\t * df.focus();\n\t * ```\n\t */\n\tconstructor(mapView: MapView) {\n\t\tthis.#pubsub = new PubSub<DynamicFocusEvents & InternalDynamicFocusEvents>();\n\t\tthis.#mapView = mapView;\n\t\tLogger.setLevel(MappedinJSLogger.logState);\n\t\tthis.#mapData = this.#mapView.getMapData();\n\t\tthis.#floorElevation = this.#mapView.currentFloor.elevation;\n\t\tthis.#cameraElevation = this.#mapView.Camera.elevation;\n\t\t// initialize the buildings\n\t\tfor (const facade of this.#mapData.getByType('facade')) {\n\t\t\tthis.#buildings.set(facade.floorStack.id, new Building(facade.floorStack, this.#mapView));\n\t\t}\n\t\tthis.#outdoors = new Outdoors(\n\t\t\tgetOutdoorFloorStack(this.#mapData.getByType('floor-stack'), this.#buildings),\n\t\t\tthis.#mapView,\n\t\t);\n\t\tthis.#mapView.on('floor-change-start', this.#handleFloorChangeStart);\n\t\tthis.#mapView.on('camera-change', this.#handleCameraChange);\n\t\tthis.#mapView.on('facades-in-view-change', this.#handleFacadesInViewChange);\n\t\tthis.#mapView.on('user-interaction-start', this.#handleUserInteractionStart);\n\t\tthis.#mapView.on('user-interaction-end', this.#handleUserInteractionEnd);\n\t}\n\n\t/**\n\t * Enables Dynamic Focus with the given options.\n\t * @param options - The options to enable Dynamic Focus with.\n\t */\n\tenable(options?: Partial<DynamicFocusState>): void {\n\t\tif (this.#enabled) {\n\t\t\tLogger.warn('enable() called on an already enabled Dynamic Focus instance.');\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#enabled = true;\n\t\tthis.#mapView.manualFloorVisibility = true;\n\t\tthis.#outdoors.show();\n\t\tthis.updateState({ ...this.#state, ...options });\n\t\t// fire the camera change event to set the initial state\n\t\tthis.#handleCameraChange({\n\t\t\tzoomLevel: this.#mapView.Camera.zoomLevel,\n\t\t\tcenter: this.#mapView.Camera.center,\n\t\t\tbearing: this.#mapView.Camera.bearing,\n\t\t\tpitch: this.#mapView.Camera.pitch,\n\t\t} as CameraTransform);\n\t\t// fire dynamic focus change to set initial state of facades\n\t\tthis.#mapView.Camera.updateFacadesInView();\n\t}\n\t/**\n\t * Disables Dynamic Focus and returns the MapView to it's previous state.\n\t */\n\tdisable(): void {\n\t\tif (!this.#enabled) {\n\t\t\tLogger.warn('disable() called on an already disabled Dynamic Focus instance.');\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#enabled = false;\n\t\tthis.#mapView.manualFloorVisibility = false;\n\t}\n\n\t/**\n\t * Returns true if Dynamic Focus is enabled.\n\t */\n\tget isEnabled(): boolean {\n\t\treturn this.#enabled;\n\t}\n\n\t/**\n\t * Returns true if the current view state is indoor.\n\t */\n\tget isIndoor() {\n\t\treturn this.#viewState === 'indoor';\n\t}\n\n\t/**\n\t * Returns true if the current view state is outdoor.\n\t */\n\tget isOutdoor() {\n\t\treturn this.#viewState === 'outdoor';\n\t}\n\n\t/**\n\t * Sets the view state to indoor, regardless of the current zoom level.\n\t */\n\tsetIndoor() {\n\t\tthis.#viewState = 'indoor';\n\t\tthis.#zoomState = 'in-range';\n\n\t\tthis.#handleViewStateChange();\n\t}\n\n\t/**\n\t * Sets the view state to outdoor, regardless of the current zoom level.\n\t */\n\tsetOutdoor() {\n\t\tthis.#viewState = 'outdoor';\n\t\tthis.#zoomState = 'out-of-range';\n\n\t\tthis.#handleViewStateChange();\n\t}\n\n\t#handleViewStateChange() {\n\t\tif (this.#state.autoFocus) {\n\t\t\t// Only set the floor if setFloorOnFocus is true and the view state changed due to a user interaction\n\t\t\t// Camera animations will not trigger a focus change until they settle.\n\t\t\tif (this.#userInteracting) {\n\t\t\t\tthis.focus();\n\t\t\t} else {\n\t\t\t\tthis.#pendingFacadeUpdate = true;\n\t\t\t}\n\t\t}\n\t\tthis.#pubsub.publish('state-change');\n\t}\n\n\t#preloadFloors(mode: DynamicFocusMode) {\n\t\tthis.#mapView.preloadFloors(\n\t\t\tthis.#mapData\n\t\t\t\t.getByType('facade')\n\t\t\t\t.map(facade => getFloorToShow(this.#buildings.get(facade.floorStack.id)!, mode, this.#floorElevation))\n\t\t\t\t.filter(f => f != null && Floor.is(f)),\n\t\t);\n\t}\n\n\t/**\n\t * Returns the facades that are currently in focus.\n\t */\n\tget focusedFacades() {\n\t\treturn [...this.#facadesInFocus];\n\t}\n\n\t/**\n\t * Subscribe to a Dynamic Focus event.\n\t */\n\ton = <EventName extends keyof DynamicFocusEvents>(\n\t\teventName: EventName,\n\t\tfn: (payload: DynamicFocusEventPayload<EventName>) => void,\n\t) => {\n\t\tthis.#pubsub.on(eventName, fn);\n\t};\n\n\t/**\n\t * Unsubscribe from a Dynamic Focus event.\n\t */\n\toff = <EventName extends keyof DynamicFocusEvents>(\n\t\teventName: EventName,\n\t\tfn: (payload: DynamicFocusEventPayload<EventName>) => void,\n\t) => {\n\t\tthis.#pubsub.off(eventName, fn);\n\t};\n\n\t/**\n\t * Returns the current state of the Dynamic Focus controller.\n\t */\n\tgetState(): DynamicFocusState {\n\t\treturn { ...this.#state };\n\t}\n\n\t/**\n\t * Updates the state of the Dynamic Focus controller.\n\t * @param state - The state to update.\n\t */\n\tupdateState(state: Partial<DynamicFocusState>) {\n\t\tlet shouldReapplyBuildingStates = false;\n\n\t\tif (state.indoorZoomThreshold != null) {\n\t\t\tstate.indoorZoomThreshold = validateZoomThreshold(\n\t\t\t\tstate.indoorZoomThreshold,\n\t\t\t\tstate?.outdoorZoomThreshold ?? this.#state.outdoorZoomThreshold,\n\t\t\t\tthis.#mapView.Camera.maxZoomLevel,\n\t\t\t\t'indoorZoomThreshold',\n\t\t\t);\n\t\t\tshouldReapplyBuildingStates = true;\n\t\t}\n\t\tif (state.outdoorZoomThreshold != null) {\n\t\t\tstate.outdoorZoomThreshold = validateZoomThreshold(\n\t\t\t\tstate.outdoorZoomThreshold,\n\t\t\t\tthis.#mapView.Camera.minZoomLevel,\n\t\t\t\tstate?.indoorZoomThreshold ?? this.#state.indoorZoomThreshold,\n\t\t\t\t'outdoorZoomThreshold',\n\t\t\t);\n\t\t\tshouldReapplyBuildingStates = true;\n\t\t}\n\n\t\tif (state.mode != null) {\n\t\t\tstate.mode = DYNAMIC_FOCUS_MODES.includes(state.mode) ? state.mode : 'default-floor';\n\t\t}\n\n\t\tif (state.autoAdjustFacadeHeights != null) {\n\t\t\tthis.#state.autoAdjustFacadeHeights = state.autoAdjustFacadeHeights;\n\t\t}\n\n\t\tif (\n\t\t\tstate.dynamicBuildingInteriors != null &&\n\t\t\tstate.dynamicBuildingInteriors !== this.#state.dynamicBuildingInteriors\n\t\t) {\n\t\t\tshouldReapplyBuildingStates = true;\n\t\t}\n\n\t\t// assign state and ignore undefined values\n\t\tthis.#state = Object.assign(\n\t\t\t{},\n\t\t\tthis.#state,\n\t\t\tObject.fromEntries(Object.entries(state).filter(([, value]) => value != null)),\n\t\t);\n\n\t\t// preload the initial floors that will be included in the mode\n\t\tif (state.mode != null && state.preloadFloors) {\n\t\t\tthis.#preloadFloors(state.mode);\n\t\t}\n\n\t\tif (shouldReapplyBuildingStates) {\n\t\t\tthis.#applyBuildingStates();\n\t\t}\n\t}\n\n\t/**\n\t * Destroys the Dynamic Focus instance and unsubscribes all MapView event listeners.\n\t */\n\tdestroy() {\n\t\tthis.disable();\n\t\tthis.#mapView.off('facades-in-view-change', this.#handleFacadesInViewChange);\n\t\tthis.#mapView.off('floor-change-start', this.#handleFloorChangeStart);\n\t\tthis.#mapView.off('camera-change', this.#handleCameraChange);\n\t\tthis.#mapView.off('user-interaction-start', this.#handleUserInteractionStart);\n\t\tthis.#mapView.off('user-interaction-end', this.#handleUserInteractionEnd);\n\t\tthis.#buildings.forEach(building => building.destroy());\n\t\tthis.#outdoors.destroy();\n\t\tthis.#pubsub.destroy();\n\t}\n\n\t/**\n\t * Perform a manual visual update of the focused facades, and optionally set the floor.\n\t * @param setFloor - Whether to set the floor. This will default to the current state of setFloorOnFocus.\n\t */\n\tasync focus(setFloor = this.#state.setFloorOnFocus) {\n\t\tif (setFloor) {\n\t\t\tif (shouldDeferSetFloor(this.#cameraElevation, this.#mapView.Camera.elevation, this.#userInteracting)) {\n\t\t\t\tthis.#cameraElevation = this.#mapView.Camera.elevation;\n\t\t\t\tthis.#pendingFacadeUpdate = true;\n\t\t\t} else {\n\t\t\t\tconst target = getSetFloorTargetFromZoomState(this.#sortedBuildingsInView, this.#outdoors, this.#zoomState);\n\n\t\t\t\tconst floor = target ? getFloorToShow(target, this.#state.mode, this.#floorElevation) : undefined;\n\n\t\t\t\tif (floor && floor.id !== this.#mapView.currentFloor.id) {\n\t\t\t\t\tthis.#mapView.setFloor(floor, { context: 'dynamic-focus' });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tawait this.#applyBuildingStates();\n\t\t// must publish after the scene is updated to ensure the focusedFacades array is up to date\n\t\tthis.#pubsub.publish('focus', { facades: this.focusedFacades });\n\t}\n\n\t/**\n\t * Preloads the initial floors for each building to improve performance when rendering the building for the first time. See {@link DynamicFocusState.preloadFloors}.\n\t */\n\tpreloadFloors() {\n\t\tthis.#preloadFloors(this.#state.mode);\n\t}\n\n\t/**\n\t * Sets the default floor for a floor stack. This is the floor that will be shown when focusing on a facade if there is no currently active floor in the stack.\n\t * See {@link resetDefaultFloorForStack} to reset the default floor.\n\t * @param floorStack - The floor stack to set the default floor for.\n\t * @param floor - The floor to set as the default floor.\n\t */\n\tsetDefaultFloorForStack(floorStack: FloorStack, floor: Floor) {\n\t\tif (!validateFloorForStack(floor, floorStack)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst building = this.#buildings.get(floorStack.id);\n\t\tif (building) {\n\t\t\tbuilding.defaultFloor = floor;\n\t\t}\n\t}\n\n\t/**\n\t * Resets the default floor for a floor stack to it's initial value.\n\t * @param floorStack - The floor stack to reset the default floor for.\n\t */\n\tresetDefaultFloorForStack(floorStack: FloorStack) {\n\t\tconst building = this.#buildings.get(floorStack.id);\n\t\tif (building) {\n\t\t\tbuilding.defaultFloor = floorStack.defaultFloor;\n\t\t}\n\t}\n\n\t/**\n\t * Returns the current default floor for a floor stack.\n\t * @param floorStack - The floor stack to get the default floor for.\n\t * @returns The current default floor for the floor stack.\n\t */\n\tgetDefaultFloorForStack(floorStack: FloorStack) {\n\t\treturn this.#buildings.get(floorStack.id)?.defaultFloor || floorStack.defaultFloor || floorStack.floors[0];\n\t}\n\n\t/**\n\t * Sets the current floor for a floor stack. If the floor stack is currently focused, this floor will become visible.\n\t * @param floorStack - The floor stack to set the current floor for.\n\t */\n\tsetCurrentFloorForStack(floorStack: FloorStack, floor: Floor) {\n\t\tif (!validateFloorForStack(floor, floorStack)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst building = this.#buildings.get(floorStack.id);\n\t\tif (building) {\n\t\t\tbuilding.activeFloor = floor;\n\t\t\tthis.#applyBuildingStates();\n\t\t}\n\t}\n\n\t/**\n\t * Excludes a floor stack from visibility changes.\n\t * @param excluded - The floor stack or stacks to exclude.\n\t */\n\texclude(excluded: FloorStack | FloorStack[]) {\n\t\tconst excludedFloorStacks = Array.isArray(excluded) ? excluded : [excluded];\n\t\tfor (const floorStack of excludedFloorStacks) {\n\t\t\tconst building = this.#buildings.get(floorStack.id);\n\t\t\tif (building) {\n\t\t\t\tbuilding.excluded = true;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Includes a floor stack in visibility changes.\n\t * @param included - The floor stack or stacks to include.\n\t */\n\tinclude(included: FloorStack | FloorStack[]) {\n\t\tconst includedFloorStacks = Array.isArray(included) ? included : [included];\n\t\tfor (const floorStack of includedFloorStacks) {\n\t\t\tconst building = this.#buildings.get(floorStack.id);\n\t\t\tif (building) {\n\t\t\t\tbuilding.excluded = false;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Returns the current floor for a floor stack.\n\t * @param floorStack - The floor stack to get the current floor for.\n\t * @returns The current floor for the floor stack.\n\t */\n\tgetCurrentFloorForStack(floorStack: FloorStack) {\n\t\treturn this.#buildings.get(floorStack.id)?.activeFloor || this.getDefaultFloorForStack(floorStack);\n\t}\n\n\t/**\n\t * Handles management of focused facades but doesn't trigger view updates unless enabled.\n\t * @see {@link focus} to manually trigger a view update.\n\t */\n\t#handleFacadesInViewChange = (event: TEvents['facades-in-view-change']) => {\n\t\tif (!this.isEnabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { facades } = event;\n\n\t\t// if the facades are the same, or we're in between outdoor/indoor, don't do anything unless we're pending a facade update\n\t\tif (arraysEqual(facades, this.focusedFacades) && this.#viewState === 'transition' && !this.#pendingFacadeUpdate) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#pendingFacadeUpdate = false;\n\n\t\tthis.#sortedBuildingsInView = [];\n\t\tthis.#buildingIdsInViewSet.clear();\n\t\tif (facades.length > 0) {\n\t\t\tfor (const facade of facades) {\n\t\t\t\tconst building = this.#buildings.get(facade.floorStack.id);\n\t\t\t\tif (building) {\n\t\t\t\t\tthis.#buildingIdsInViewSet.add(building.id);\n\t\t\t\t\tthis.#sortedBuildingsInView.push(building);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.#state.autoFocus) {\n\t\t\tthis.focus();\n\t\t}\n\t};\n\t/**\n\t * Handles floor and facade visibility when the floor changes.\n\t */\n\t#handleFloorChangeStart = async (event: TEvents['floor-change-start']) => {\n\t\tif (!this.isEnabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { floor: newFloor } = event;\n\t\tconst building = this.#buildings.get(newFloor.floorStack.id);\n\t\tif (building) {\n\t\t\tbuilding.activeFloor = newFloor;\n\t\t}\n\t\t// Don't update elevation when switching to outdoor floor stack\n\t\tif (building?.excluded === false && !this.#outdoors.matchesFloorStack(newFloor.floorStack)) {\n\t\t\tthis.#floorElevation = newFloor.elevation;\n\t\t}\n\n\t\tif (this.#mapView.manualFloorVisibility === true) {\n\t\t\tif (event.reason !== 'dynamic-focus') {\n\t\t\t\tawait this.#applyBuildingStates(newFloor);\n\t\t\t\t// Despite this not really being a focus event, we've changed the focused facades, so we need to publish it\n\t\t\t\tthis.#pubsub.publish('focus', { facades: this.focusedFacades });\n\t\t\t}\n\n\t\t\tconst altitude = building?.floorsAltitudesMap.get(newFloor.elevation)?.altitude ?? 0;\n\t\t\tif (\n\t\t\t\tthis.#mapView.options.multiFloorView != null &&\n\t\t\t\tthis.#mapView.options.multiFloorView?.enabled &&\n\t\t\t\tthis.#mapView.options.multiFloorView?.updateCameraElevationOnFloorChange &&\n\t\t\t\tthis.#mapView.Camera.elevation !== altitude\n\t\t\t) {\n\t\t\t\tthis.#mapView.Camera.animateElevation(altitude, {\n\t\t\t\t\tduration: 750,\n\t\t\t\t\teasing: 'ease-in-out',\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t};\n\n\t#handleUserInteractionStart = () => {\n\t\tthis.#userInteracting = true;\n\t};\n\t#handleUserInteractionEnd = () => {\n\t\tthis.#userInteracting = false;\n\t};\n\n\t/**\n\t * Handles camera moving in and out of zoom range and fires a focus event if the camera is in range.\n\t */\n\t#handleCameraChange = (event: TEvents['camera-change']) => {\n\t\tif (!this.isEnabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { zoomLevel } = event;\n\t\tconst newZoomState = getZoomState(zoomLevel, this.#state.indoorZoomThreshold, this.#state.outdoorZoomThreshold);\n\n\t\tif (this.#zoomState !== newZoomState) {\n\t\t\tthis.#zoomState = newZoomState;\n\n\t\t\tif (newZoomState === 'in-range') {\n\t\t\t\tthis.setIndoor();\n\t\t\t} else if (newZoomState === 'out-of-range') {\n\t\t\t\tthis.setOutdoor();\n\t\t\t}\n\t\t}\n\t};\n\n\t#updateFloorVisibility(floorStates: BuildingFloorStackState['floorStates'], shouldShow: boolean, inFocus?: boolean) {\n\t\tfloorStates.forEach(floorState => {\n\t\t\tif (floorState.floor) {\n\t\t\t\tif (shouldShow) {\n\t\t\t\t\tconst state =\n\t\t\t\t\t\tinFocus !== undefined\n\t\t\t\t\t\t\t? ({\n\t\t\t\t\t\t\t\t\t...floorState.state,\n\t\t\t\t\t\t\t\t\tlabels: {\n\t\t\t\t\t\t\t\t\t\t...floorState.state.labels,\n\t\t\t\t\t\t\t\t\t\tenabled: floorState.state.labels.enabled && inFocus,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tmarkers: {\n\t\t\t\t\t\t\t\t\t\t...floorState.state.markers,\n\t\t\t\t\t\t\t\t\t\tenabled: floorState.state.markers.enabled && inFocus,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tocclusion: {\n\t\t\t\t\t\t\t\t\t\t...floorState.state.occlusion,\n\t\t\t\t\t\t\t\t\t\t// We don't want this floor to occlude if it's not in focus\n\t\t\t\t\t\t\t\t\t\t// Allows us to show a label above this floor while it's not active\n\t\t\t\t\t\t\t\t\t\tenabled: floorState.state.occlusion.enabled && inFocus,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t } satisfies TFloorState)\n\t\t\t\t\t\t\t: floorState.state;\n\n\t\t\t\t\tthis.#mapView.updateState(floorState.floor, state);\n\t\t\t\t} else {\n\t\t\t\t\tthis.#mapView.updateState(floorState.floor, { visible: false });\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tasync #animateIndoorSequence(\n\t\tbuilding: Building,\n\t\tfloorStackState: BuildingFloorStackState,\n\t\tfacadeState: BuildingFacadeState,\n\t\tinFocus: boolean,\n\t) {\n\t\t// show floor first then fade in the facade\n\t\tthis.#updateFloorVisibility(floorStackState.floorStates, true, inFocus);\n\n\t\treturn building.animateFacade(facadeState.state, this.#state.indoorAnimationOptions);\n\t}\n\n\tasync #animateOutdoorSequence(\n\t\tbuilding: Building,\n\t\tfloorStackState: BuildingFloorStackState,\n\t\tfacadeState: BuildingFacadeState,\n\t\tfloorStackIdsInNavigation: string[],\n\t) {\n\t\t// fade in facade then hide floors when complete\n\t\tconst result = await building.animateFacade(facadeState.state, this.#state.outdoorAnimationOptions);\n\n\t\tif (result.result === 'completed') {\n\t\t\t// Re-check if we should still show indoor after animation completes\n\t\t\tthis.#updateFloorVisibility(\n\t\t\t\tfloorStackState.floorStates,\n\t\t\t\tshouldShowIndoor(\n\t\t\t\t\tbuilding,\n\t\t\t\t\tthis.#mapView.currentFloor,\n\t\t\t\t\tthis.#zoomState === 'in-range',\n\t\t\t\t\tthis.#buildingIdsInViewSet.has(building.id),\n\t\t\t\t\tthis.#state.mode,\n\t\t\t\t\tthis.#floorElevation,\n\t\t\t\t\tfloorStackIdsInNavigation.includes(building.floorStack.id),\n\t\t\t\t\tthis.#state.dynamicBuildingInteriors,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t#applyBuildingStates = async (newFloor?: Floor) => {\n\t\tif (this.#mapView.manualFloorVisibility !== true || !this.isEnabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentFloor = newFloor || this.#mapView.currentFloor;\n\t\tconst multiFloorView = this.#mapView.options.multiFloorView;\n\t\tconst floorIdsInNavigation = this.#mapView.Navigation?.floors?.map(f => f.id) || [];\n\t\tconst floorStackIdsInNavigation = this.#mapView.Navigation?.floorStacks.map(fs => fs.id) || [];\n\n\t\t// Create a new promise for this update\n\t\tconst updatePromise = new Promise<void>(async resolve => {\n\t\t\t// Wait for the previous update to complete\n\t\t\tawait this.sceneUpdateQueue;\n\n\t\t\tconst buildingStates = getBuildingStates(\n\t\t\t\tArray.from(this.#buildings.values()),\n\t\t\t\tthis.#buildingIdsInViewSet,\n\t\t\t\tcurrentFloor,\n\t\t\t\tthis.#zoomState,\n\t\t\t\tthis.#state.mode,\n\t\t\t\tthis.#floorElevation,\n\t\t\t\tfloorIdsInNavigation,\n\t\t\t\tfloorStackIdsInNavigation,\n\t\t\t\tmultiFloorView,\n\t\t\t\tthis.#state.customMultiFloorVisibilityState ?? getMultiFloorState,\n\t\t\t\tthis.#state.dynamicBuildingInteriors,\n\t\t\t);\n\n\t\t\tconst floorStackStates: BuildingFloorStackState[] = [];\n\t\t\tawait Promise.all(\n\t\t\t\tArray.from(buildingStates.values()).map(async buildingState => {\n\t\t\t\t\tconst { building, showIndoor, floorStackState, facadeState, inFocus } = buildingState;\n\n\t\t\t\t\tfloorStackStates.push(floorStackState);\n\n\t\t\t\t\tconst animation = getBuildingAnimationType(building, showIndoor);\n\n\t\t\t\t\tif (animation === 'indoor') {\n\t\t\t\t\t\treturn this.#animateIndoorSequence(building, floorStackState, facadeState, inFocus);\n\t\t\t\t\t} else if (animation === 'outdoor') {\n\t\t\t\t\t\treturn this.#animateOutdoorSequence(building, floorStackState, facadeState, floorStackIdsInNavigation);\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t);\n\n\t\t\tthis.#mapView.Outdoor.setOpacity(getOutdoorOpacity(floorStackStates, this.#state.mode));\n\n\t\t\t// Filter #facadesInFocus to maintain sort order, keeping only buildings with showIndoor true\n\t\t\tthis.#facadesInFocus = this.#sortedBuildingsInView\n\t\t\t\t.filter(building => buildingStates.get(building.id)?.showIndoor === true)\n\t\t\t\t.map(building => building.facade);\n\n\t\t\tthis.#pubsub.publish('focus', { facades: this.#facadesInFocus });\n\n\t\t\tresolve();\n\t\t});\n\n\t\t// Update the queue with the new promise\n\t\tthis.sceneUpdateQueue = updatePromise;\n\n\t\treturn updatePromise;\n\t};\n}\n", "/**\n * Compare two arrays for equality\n */\nexport function arraysEqual(arr1: any[] | null | undefined, arr2: any[] | null | undefined) {\n\tif (arr1 == null || arr2 == null) {\n\t\treturn arr1 === arr2;\n\t}\n\n\tif (arr1.length !== arr2.length) {\n\t\treturn false;\n\t}\n\n\tfor (let i = 0; i < arr1.length; i++) {\n\t\tif (arr1[i] !== arr2[i]) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n", "/**\n * Generic PubSub class implementing the Publish-Subscribe pattern for event handling.\n *\n * @template EVENT_PAYLOAD - The type of the event payload.\n * @template EVENT - The type of the event.\n */\nexport class PubSub<EVENT_PAYLOAD, EVENT extends keyof EVENT_PAYLOAD = keyof EVENT_PAYLOAD> {\n\t/**\n\t * @private\n\t * @internal\n\t */\n\tprivate _subscribers: any = {};\n\t/**\n\t * @private\n\t * @internal\n\t */\n\tprivate _destroyed = false;\n\n\t/**\n\t * @private\n\t * @internal\n\t */\n\tpublish<EVENT_NAME extends EVENT>(eventName: EVENT_NAME, data?: EVENT_PAYLOAD[EVENT_NAME]) {\n\t\tif (!this._subscribers || !this._subscribers[eventName] || this._destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._subscribers[eventName]!.forEach(function (fn) {\n\t\t\tif (typeof fn !== 'function') {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfn(data);\n\t\t});\n\t}\n\n\t/**\n\t * Subscribe a function to an event.\n\t *\n\t * @param eventName An event name which, when fired, will call the provided\n\t * function.\n\t * @param fn A callback that gets called when the corresponding event is fired. The\n\t * callback will get passed an argument with a type that's one of event payloads.\n\t * @example\n\t * // Subscribe to the 'click' event\n\t * const handler = (event) => {\n\t * const { coordinate } = event;\n\t * const { latitude, longitude } = coordinate;\n\t * \tconsole.log(`Map was clicked at ${latitude}, ${longitude}`);\n\t * };\n\t * map.on('click', handler);\n\t */\n\ton<EVENT_NAME extends EVENT>(\n\t\teventName: EVENT_NAME,\n\t\tfn: (\n\t\t\tpayload: EVENT_PAYLOAD[EVENT_NAME] extends {\n\t\t\t\tdata: null;\n\t\t\t}\n\t\t\t\t? EVENT_PAYLOAD[EVENT_NAME]['data']\n\t\t\t\t: EVENT_PAYLOAD[EVENT_NAME],\n\t\t) => void,\n\t) {\n\t\tif (!this._subscribers || this._destroyed) {\n\t\t\tthis._subscribers = {};\n\t\t}\n\t\tthis._subscribers[eventName] = this._subscribers[eventName] || [];\n\t\tthis._subscribers[eventName]!.push(fn);\n\t}\n\n\t/**\n\t * Unsubscribe a function previously subscribed with {@link on}\n\t *\n\t * @param eventName An event name to which the provided function was previously\n\t * subscribed.\n\t * @param fn A function that was previously passed to {@link on}. The function must\n\t * have the same reference as the function that was subscribed.\n\t * @example\n\t * // Unsubscribe from the 'click' event\n\t * const handler = (event) => {\n\t * \tconsole.log('Map was clicked', event);\n\t * };\n\t * map.off('click', handler);\n\t */\n\toff<EVENT_NAME extends EVENT>(\n\t\teventName: EVENT_NAME,\n\t\tfn: (\n\t\t\tpayload: EVENT_PAYLOAD[EVENT_NAME] extends {\n\t\t\t\tdata: null;\n\t\t\t}\n\t\t\t\t? EVENT_PAYLOAD[EVENT_NAME]['data']\n\t\t\t\t: EVENT_PAYLOAD[EVENT_NAME],\n\t\t) => void,\n\t) {\n\t\tif (!this._subscribers || this._subscribers[eventName] == null || this._destroyed) {\n\t\t\treturn;\n\t\t}\n\t\tconst itemIdx = this._subscribers[eventName]!.indexOf(fn);\n\n\t\tif (itemIdx !== -1) {\n\t\t\tthis._subscribers[eventName]!.splice(itemIdx, 1);\n\t\t}\n\t}\n\t/**\n\t * @private\n\t * @internal\n\t */\n\tdestroy() {\n\t\tthis._destroyed = true;\n\t\tthis._subscribers = {};\n\t}\n}\n", "import type { MapView, TAnimateStateResult, TFacadeState } from '@mappedin/mappedin-js';\nimport { Facade, Floor, FloorStack } from '@mappedin/mappedin-js';\nimport type { DynamicFocusAnimationOptions } from './types';\n\nexport class Building {\n\t__type = 'building';\n\t#floorStack: FloorStack;\n\t#floorsById = new Map<string, Floor>();\n\t#floorsByElevation = new Map<number, Floor>();\n\t#floorsByElevationSorted: Floor[] = [];\n\t#mapView: MapView;\n\t#animationInProgress: { state: TFacadeState; animation: ReturnType<MapView['animateState']> } | undefined;\n\n\tdefaultFloor: Floor;\n\tactiveFloor: Floor;\n\texcluded = false;\n\tfloorsAltitudesMap: Map<number, { altitude: number; effectiveHeight: number }> = new Map();\n\taboveGroundFloors: Floor[] = [];\n\n\tconstructor(floorStack: FloorStack, mapView: MapView) {\n\t\tthis.#floorStack = floorStack;\n\t\tthis.#floorsById = new Map(floorStack.floors.map(floor => [floor.id, floor]));\n\t\tthis.#floorsByElevation = new Map(floorStack.floors.map(floor => [floor.elevation, floor]));\n\t\tthis.#floorsByElevationSorted = Array.from(this.#floorsByElevation.values()).sort(\n\t\t\t(a, b) => a.elevation - b.elevation,\n\t\t);\n\t\tthis.defaultFloor = floorStack.defaultFloor;\n\t\tthis.activeFloor = this.defaultFloor;\n\t\tthis.#mapView = mapView;\n\t\tthis.aboveGroundFloors = this.#floorsByElevationSorted.filter(floor => floor.elevation >= 0);\n\n\t\tconst sortedSpaces = floorStack.facade?.spaces\n\t\t\t.map(space => this.#mapView.getState(space))\n\t\t\t.sort((a, b) => a.altitude - b.altitude);\n\t\tif (sortedSpaces && sortedSpaces.length === this.aboveGroundFloors.length) {\n\t\t\tfor (const idx in this.aboveGroundFloors) {\n\t\t\t\tconst floor = this.aboveGroundFloors[idx];\n\t\t\t\tconst space = sortedSpaces[idx];\n\t\t\t\tthis.floorsAltitudesMap.set(floor.elevation, {\n\t\t\t\t\taltitude: space.altitude,\n\t\t\t\t\teffectiveHeight: space.height,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tget id() {\n\t\treturn this.#floorStack.id;\n\t}\n\n\tget name() {\n\t\treturn this.#floorStack.name;\n\t}\n\n\tget floors() {\n\t\treturn this.#floorStack.floors;\n\t}\n\n\tget floorStack() {\n\t\treturn this.#floorStack;\n\t}\n\n\tget facade() {\n\t\t// the floorstack must have a facade if we created a building for it\n\t\treturn this.#floorStack.facade!;\n\t}\n\n\tget isCurrentFloorStack() {\n\t\treturn this.id === this.#mapView.currentFloorStack.id;\n\t}\n\n\tget isIndoor() {\n\t\tconst state = this.#mapView.getState(this.facade);\n\n\t\treturn this.isCurrentFloorStack || (state?.visible === false && state?.opacity === 0);\n\t}\n\n\tget canSetFloor() {\n\t\treturn this.isIndoor || !this.excluded;\n\t}\n\n\t#maxElevation: number | undefined;\n\tget maxElevation() {\n\t\tif (this.#maxElevation == null) {\n\t\t\tthis.#maxElevation = Math.max(...this.#floorsByElevation.keys());\n\t\t}\n\n\t\treturn this.#maxElevation;\n\t}\n\n\t#minElevation: number | undefined;\n\tget minElevation() {\n\t\tif (this.#minElevation == null) {\n\t\t\tthis.#minElevation = Math.min(...this.#floorsByElevation.keys());\n\t\t}\n\n\t\treturn this.#minElevation;\n\t}\n\n\thas(f: Floor | FloorStack | Facade) {\n\t\tif (Floor.is(f)) {\n\t\t\treturn this.#floorsById.has(f.id);\n\t\t}\n\n\t\tif (FloorStack.is(f)) {\n\t\t\treturn f.id === this.#floorStack.id;\n\t\t}\n\n\t\tif (Facade.is(f)) {\n\t\t\treturn f.id === this.facade.id;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tgetFloorByElevation(elevation: number) {\n\t\treturn this.#floorsByElevation.get(elevation);\n\t}\n\n\tgetNearestFloorByElevation(targetElevation: number): Floor | undefined {\n\t\tconst exactMatch = this.getFloorByElevation(targetElevation);\n\t\tif (exactMatch) {\n\t\t\treturn exactMatch;\n\t\t}\n\n\t\tif (targetElevation >= 0) {\n\t\t\t// For positive elevations, return highest floor if target is above max\n\t\t\tif (targetElevation > this.maxElevation) {\n\t\t\t\treturn this.#floorsByElevationSorted[this.#floorsByElevationSorted.length - 1];\n\t\t\t}\n\n\t\t\t// Search backwards from the end\n\t\t\tfor (let i = this.#floorsByElevationSorted.length - 1; i >= 0; i--) {\n\t\t\t\tconst floor = this.#floorsByElevationSorted[i];\n\t\t\t\tif (floor.elevation <= targetElevation) {\n\t\t\t\t\treturn floor;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// For negative elevations (basements), return the lowest floor if target is below min\n\t\t\tif (targetElevation < this.minElevation) {\n\t\t\t\treturn this.#floorsByElevationSorted[0];\n\t\t\t}\n\n\t\t\t// Search forwards from the start\n\t\t\tfor (const floor of this.#floorsByElevationSorted) {\n\t\t\t\tif (floor.elevation >= targetElevation) {\n\t\t\t\t\treturn floor;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\tgetHighestFloor(): Floor {\n\t\treturn this.#floorsByElevationSorted[this.#floorsByElevationSorted.length - 1];\n\t}\n\n\tcancelAnimation() {\n\t\tif (this.#animationInProgress) {\n\t\t\tthis.#animationInProgress.animation.cancel();\n\t\t\tthis.#animationInProgress = undefined;\n\t\t}\n\t}\n\n\tasync animateFacade(\n\t\tnewState: TFacadeState,\n\t\toptions: DynamicFocusAnimationOptions = { duration: 150 },\n\t): Promise<TAnimateStateResult> {\n\t\tconst currentState = this.#animationInProgress?.state || this.#mapView.getState(this.facade);\n\t\tif (\n\t\t\t!currentState ||\n\t\t\t!newState ||\n\t\t\t(currentState?.opacity === newState.opacity && currentState?.visible === newState.visible)\n\t\t) {\n\t\t\t// nothing to do\n\t\t\treturn { result: 'completed' };\n\t\t}\n\n\t\tthis.cancelAnimation();\n\t\tconst { opacity, visible } = newState;\n\n\t\t// always set facade visible so it can be seen during animation\n\t\tthis.#mapView.updateState(this.facade, {\n\t\t\tvisible: true,\n\t\t});\n\n\t\tif (opacity !== undefined) {\n\t\t\tthis.#animationInProgress = {\n\t\t\t\tanimation: this.#mapView.animateState(\n\t\t\t\t\tthis.facade,\n\t\t\t\t\t{\n\t\t\t\t\t\topacity,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tduration: options.duration,\n\t\t\t\t\t},\n\t\t\t\t),\n\t\t\t\tstate: newState,\n\t\t\t};\n\t\t\tconst result = await this.#animationInProgress.animation;\n\n\t\t\tthis.#animationInProgress = undefined;\n\n\t\t\tif (result.result === 'cancelled') {\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\n\t\tif (visible === false) {\n\t\t\tthis.#mapView.updateState(this.facade, {\n\t\t\t\tvisible,\n\t\t\t});\n\t\t}\n\n\t\treturn { result: 'completed' };\n\t}\n\n\tdestroy() {\n\t\tthis.cancelAnimation();\n\t\t// Hide all floors except current floor\n\t\tthis.#floorStack.floors.forEach(floor => {\n\t\t\tthis.#mapView.updateState(floor, {\n\t\t\t\tvisible: floor.id === this.#mapView.currentFloor.id,\n\t\t\t});\n\t\t});\n\t\t// Show the facade if the current floor is not in this building\n\t\tif (!this.has(this.#mapView.currentFloor)) {\n\t\t\tthis.#mapView.updateState(this.facade, {\n\t\t\t\tvisible: true,\n\t\t\t\topacity: 1,\n\t\t\t});\n\t\t}\n\t}\n}\n", "import type { Facade, Floor, FloorStack, TFloorState } from '@mappedin/mappedin-js';\nimport type { Building } from './building';\nimport type {\n\tBuildingAnimation,\n\tBuildingFacadeState,\n\tBuildingFloorStackState,\n\tDynamicFocusMode,\n\tMultiFloorVisibilityState,\n\tZoomState,\n} from './types';\nimport type { Outdoors } from './outdoors';\n\n/**\n * Calculates the zoom state based on camera zoom level and thresholds.\n */\nexport function getZoomState(zoomLevel: number, indoorThreshold: number, outdoorThreshold: number): ZoomState {\n\tif (zoomLevel >= indoorThreshold) {\n\t\treturn 'in-range';\n\t}\n\tif (zoomLevel <= outdoorThreshold) {\n\t\treturn 'out-of-range';\n\t}\n\n\treturn 'transition';\n}\n\nexport function getFloorToShow(\n\ttarget: Building | Outdoors,\n\tmode: DynamicFocusMode,\n\televation: number,\n): Floor | undefined {\n\tif (target.__type === 'outdoors' && 'floor' in target) {\n\t\treturn target.floor;\n\t}\n\n\tconst building = target as Building;\n\tif (building.excluded) {\n\t\treturn building.activeFloor;\n\t}\n\n\tswitch (mode) {\n\t\tcase 'lock-elevation':\n\t\t\treturn building.getFloorByElevation(elevation);\n\t\tcase 'nearest-elevation':\n\t\t\treturn building.getNearestFloorByElevation(elevation);\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\t// if the building is already showing, don't switch to the default floor\n\treturn building.isIndoor ? building.activeFloor : building.defaultFloor;\n}\n\nexport function getFacadeState(facade: Facade, inFocus: boolean): BuildingFacadeState {\n\treturn {\n\t\tfacade,\n\t\tstate: {\n\t\t\ttype: 'facade',\n\t\t\tvisible: !inFocus,\n\t\t\topacity: inFocus ? 0 : 1,\n\t\t},\n\t};\n}\n\nexport function getSingleBuildingState(\n\tfloorStack: FloorStack,\n\tcurrentFloor: Floor,\n\tinFocus: boolean,\n): BuildingFloorStackState {\n\treturn {\n\t\toutdoorOpacity: 1,\n\t\tfloorStates: floorStack.floors.map(f => {\n\t\t\tconst visible = f.id === currentFloor.id && inFocus;\n\n\t\t\treturn {\n\t\t\t\tfloor: f,\n\t\t\t\tstate: {\n\t\t\t\t\ttype: 'floor',\n\t\t\t\t\tvisible: visible,\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\tvisible: visible,\n\t\t\t\t\t},\n\t\t\t\t\tlabels: {\n\t\t\t\t\t\tenabled: visible,\n\t\t\t\t\t},\n\t\t\t\t\tmarkers: {\n\t\t\t\t\t\tenabled: visible,\n\t\t\t\t\t},\n\t\t\t\t\tfootprint: {\n\t\t\t\t\t\tvisible: false,\n\t\t\t\t\t},\n\t\t\t\t\tocclusion: {\n\t\t\t\t\t\tenabled: false,\n\t\t\t\t\t},\n\t\t\t\t} as Required<TFloorState>,\n\t\t\t};\n\t\t}),\n\t};\n}\n\n/**\n * Calculates the outdoor opacity based on floor stack states and mode.\n */\nexport function getOutdoorOpacity(floorStackStates: BuildingFloorStackState[], mode: DynamicFocusMode): number {\n\tif (!mode.includes('lock-elevation')) {\n\t\treturn 1;\n\t}\n\n\tfor (const state of floorStackStates) {\n\t\tif (state.outdoorOpacity >= 0 && state.outdoorOpacity <= 1) {\n\t\t\treturn state.outdoorOpacity;\n\t\t}\n\t}\n\n\treturn 1;\n}\n\nexport function getSetFloorTargetFromZoomState(\n\tbuildings: Building[],\n\toutdoors: Outdoors,\n\tzoomState: ZoomState,\n): Building | Outdoors | undefined {\n\tswitch (zoomState) {\n\t\tcase 'in-range':\n\t\t\treturn buildings[0]?.canSetFloor ? buildings[0] : undefined;\n\t\tcase 'out-of-range':\n\t\t\treturn outdoors;\n\t\tcase 'transition':\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n}\n\n/**\n * Gets the building states for all buildings.\n */\nexport function getBuildingStates(\n\tbuildings: Building[],\n\tinViewSet: Set<string>,\n\tcurrentFloor: Floor,\n\tzoomState: ZoomState,\n\tmode: DynamicFocusMode,\n\televation: number,\n\tfloorIdsInNavigation: string[],\n\tfloorStackIdsInNavigation: string[],\n\tmultiFloorView: any,\n\tgetMultiFloorState: MultiFloorVisibilityState,\n\tdynamicBuildingInteriors: boolean,\n): Map<\n\tstring,\n\t{\n\t\tbuilding: Building;\n\t\tshowIndoor: boolean;\n\t\tfloorStackState: BuildingFloorStackState;\n\t\tfacadeState: BuildingFacadeState;\n\t\tinFocus: boolean;\n\t\tfloorToShow: Floor | undefined;\n\t}\n> {\n\tconst buildingStates = new Map();\n\n\tfor (const building of buildings) {\n\t\tconst inCameraView = inViewSet.has(building.id);\n\t\tconst showIndoor = shouldShowIndoor(\n\t\t\tbuilding,\n\t\t\tcurrentFloor,\n\t\t\tzoomState === 'in-range',\n\t\t\tinCameraView,\n\t\t\tmode,\n\t\t\televation,\n\t\t\tfloorStackIdsInNavigation.includes(building.id),\n\t\t\tdynamicBuildingInteriors,\n\t\t);\n\n\t\tconst floorToShow =\n\t\t\tcurrentFloor.floorStack.id === building.id ? building.activeFloor : getFloorToShow(building, mode, elevation);\n\n\t\tconst floorStackState = multiFloorView.enabled\n\t\t\t? getMultiFloorState(\n\t\t\t\t\tbuilding.floors,\n\t\t\t\t\tfloorToShow || building.activeFloor,\n\t\t\t\t\tmultiFloorView?.floorGap,\n\t\t\t\t\tfloorIdsInNavigation,\n\t\t\t\t\tbuilding.floorsAltitudesMap,\n\t\t\t )\n\t\t\t: getSingleBuildingState(building.floorStack, floorToShow || building.activeFloor, showIndoor);\n\n\t\tconst facadeState = getFacadeState(building.facade, showIndoor);\n\t\tbuildingStates.set(building.id, {\n\t\t\tbuilding,\n\t\t\tshowIndoor,\n\t\t\tfloorStackState,\n\t\t\tfacadeState,\n\t\t\tinFocus: inCameraView,\n\t\t\tfloorToShow,\n\t\t});\n\t}\n\n\treturn buildingStates;\n}\n\nexport function getBuildingAnimationType(building: Building, showIndoor: boolean): BuildingAnimation {\n\tif (building.excluded) {\n\t\treturn 'none';\n\t}\n\n\tif (showIndoor) {\n\t\treturn 'indoor';\n\t}\n\n\treturn 'outdoor';\n}\n\n/**\n * Determines if a building's indoor floors should be shown through a number of different state checks.\n */\nexport function shouldShowIndoor(\n\tbuilding: Building,\n\tcurrentFloor: Floor,\n\tinRange: boolean,\n\tinFocus: boolean,\n\tmode: DynamicFocusMode,\n\televation: number,\n\tinNavigation: boolean,\n\tdynamicBuildingInteriors: boolean,\n): boolean {\n\t// always show the current floor regardless of any other states\n\tif (building.id === currentFloor.floorStack.id) {\n\t\treturn true;\n\t}\n\n\t// if the building is excluded, we don't control the visibility, so don't show it\n\tif (building.excluded) {\n\t\treturn false;\n\t}\n\n\t// if it's not excluded, always show the navigation\n\tif (inNavigation === true) {\n\t\treturn true;\n\t}\n\n\t// Without dynamic building interiors, we only rely on whether the current floor is indoor or outdoor\n\tif (!dynamicBuildingInteriors) {\n\t\treturn currentFloor.floorStack.type !== 'Outdoor';\n\t}\n\n\t// the following cases rely on the camera being in range\n\tif (!inRange) {\n\t\treturn false;\n\t}\n\n\t// the following cases rely on the building being in focus\n\tif (!inFocus) {\n\t\treturn false;\n\t}\n\n\tswitch (mode) {\n\t\tcase 'lock-elevation':\n\t\t\treturn building.getFloorByElevation(elevation) != null;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\treturn true;\n}\n\nexport function shouldDeferSetFloor(\n\ttrackedCameraElevation: number,\n\tcurrentCameraElevation: number,\n\tuserInteracting: boolean,\n): boolean {\n\treturn trackedCameraElevation !== currentCameraElevation && !userInteracting;\n}\n", "import type { Facade, Floor, TFacadeState } from '@mappedin/mappedin-js';\nimport type { VisibilityState as BuildingFloorStackState } from '../../mappedin-js/src/api-geojson/multi-floor';\n\nexport type MultiFloorVisibilityState = (\n\tfloors: Floor[],\n\tcurrentFloor: Floor,\n\tfloorGap: number,\n\tfloorIdsInNavigation: Floor['id'][],\n\tfloorsVisualHeightMap?: Map<number, { altitude: number; effectiveHeight: number }>,\n) => BuildingFloorStackState;\n\nexport type DynamicFocusAnimationOptions = {\n\t/**\n\t * The duration of the animation in milliseconds.\n\t * @default 150\n\t */\n\tduration: number;\n};\n\n/**\n * Array of valid dynamic focus modes for runtime validation.\n */\nexport const DYNAMIC_FOCUS_MODES = ['default-floor', 'lock-elevation', 'nearest-elevation'] as const;\n\n/**\n * The mode which determines the indoor floor to reveal when the camera focuses on a facade.\n * - 'default-floor' - Show the default floor of the floor stack.\n * - 'lock-elevation' - Show the floor at the current elevation, if possible.\n * When a floor stack does not have a floor at the current elevation, no indoor floor will be shown.\n * - 'nearest-elevation' - Show the floor at the current elevation, if possible.\n * When a floor stack does not have a floor at the current elevation, show the indoor floor at the nearest lower elevation.\n */\nexport type DynamicFocusMode = (typeof DYNAMIC_FOCUS_MODES)[number];\n\n/**\n * State of the Dynamic Focus controller.\n */\nexport type DynamicFocusState = {\n\t/**\n\t * Whether to automatically focus on the outdoors when the camera moves in range.\n\t * @default true\n\t */\n\tautoFocus: boolean;\n\t/**\n\t * The zoom level at which the camera will fade out the facades and fade in the indoor floors.\n\t * @default 18\n\t */\n\tindoorZoomThreshold: number;\n\t/**\n\t * The zoom level at which the camera will fade in the facades and fade out the indoor floors.\n\t * @default 17\n\t */\n\toutdoorZoomThreshold: number;\n\t/**\n\t * Whether to set the floor to the outdoors when the camera moves in range.\n\t * @default true\n\t */\n\tsetFloorOnFocus: boolean;\n\t/**\n\t * Options for the animation when fading out the facade to reveal the interior.\n\t */\n\tindoorAnimationOptions: DynamicFocusAnimationOptions;\n\t/**\n\t * Options for the animation when fading in the facade to hide the interior.\n\t */\n\toutdoorAnimationOptions: DynamicFocusAnimationOptions;\n\t/**\n\t * The mode of the Dynamic Focus controller.\n\t * @default 'default-floor'\n\t */\n\tmode: DynamicFocusMode;\n\t/**\n\t * Whether to automatically adjust facade heights to align with floor boundaries in multi-floor buildings.\n\t * @default false\n\t */\n\tautoAdjustFacadeHeights: boolean;\n\t/**\n\t * Whether to automatically hide the indoors of buildings not in or near the camera's view.\n\t * @default true\n\t */\n\tdynamicBuildingInteriors: boolean;\n\t/**\n\t * Whether to preload the geometry of the initial floors in each building. Improves performance when rendering the building for the first time.\n\t * @default true\n\t */\n\tpreloadFloors: boolean;\n\n\t/**\n\t * @experimental\n\t * @internal\n\t * A custom function to override the default floor visibility state.\n\t * This is useful for customizing the floor visibility state for a specific building.\n\t */\n\tcustomMultiFloorVisibilityState?: MultiFloorVisibilityState;\n};\n\n/**\n * Internal events emitted for updating React state.\n */\nexport type InternalDynamicFocusEvents = {\n\t'state-change': undefined;\n};\n\n/**\n * Events emitted by the Dynamic Focus controller.\n */\nexport type DynamicFocusEvents = {\n\t/**\n\t * Emitted when the Dynamic Focus controller triggers a focus update either from a camera change or manually calling `focus()`.\n\t */\n\tfocus: {\n\t\tfacades: Facade[];\n\t};\n};\n\nexport type DynamicFocusEventPayload<EventName extends keyof DynamicFocusEvents> =\n\tDynamicFocusEvents[EventName] extends { data: null }\n\t\t? DynamicFocusEvents[EventName]['data']\n\t\t: DynamicFocusEvents[EventName];\n\nexport type BuildingFacadeState = {\n\tfacade: Facade;\n\tstate: TFacadeState;\n};\n\nexport type BuildingState = BuildingFloorStackState & {\n\tfacadeState: BuildingFacadeState;\n};\n\nexport type ZoomState = 'in-range' | 'out-of-range' | 'transition';\nexport type ViewState = 'indoor' | 'outdoor' | 'transition';\n\nexport type BuildingAnimation = 'indoor' | 'outdoor' | 'none';\n\nexport type { BuildingFloorStackState };\n", "import { Floor, FloorStack } from '@mappedin/mappedin-js';\nimport { clampWithWarning } from '@packages/internal/common/math-utils';\nimport Logger from '@packages/internal/common/Mappedin.Logger';\n\n/**\n * Validates that a floor belongs to the specified floor stack.\n */\nexport function validateFloorForStack(floor: Floor, floorStack: FloorStack): boolean {\n\tif (!Floor.is(floor) || floor?.floorStack == null || !FloorStack.is(floorStack)) {\n\t\treturn false;\n\t}\n\n\tif (floor.floorStack.id !== floorStack.id) {\n\t\tLogger.warn(`Floor (${floor.id}) does not belong to floor stack (${floorStack.id}).`);\n\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n/**\n * Validates and clamps zoom threshold values.\n */\nexport function validateZoomThreshold(value: number, min: number, max: number, name: string): number {\n\treturn clampWithWarning(value, min, max, `${name} must be between ${min} and ${max}.`);\n}\n", "/* eslint-disable no-console*/\nexport const MI_DEBUG_KEY = 'mi-debug';\nexport const MI_ERROR_LABEL = '[MappedinJS]';\n\nexport enum E_SDK_LOG_LEVEL {\n\tLOG,\n\tWARN,\n\tERROR,\n\tSILENT,\n}\n\nexport function createLogger(name = '', { prefix = MI_ERROR_LABEL } = {}) {\n\tconst label = `${prefix}${name ? `-${name}` : ''}`;\n\n\tconst rnDebug = (type: 'log' | 'warn' | 'error', args: any[]) => {\n\t\tif (typeof window !== 'undefined' && (window as any).rnDebug) {\n\t\t\tconst processed = args.map(arg => {\n\t\t\t\tif (arg instanceof Error && arg.stack) {\n\t\t\t\t\treturn `${arg.message}\\n${arg.stack}`;\n\t\t\t\t}\n\n\t\t\t\treturn arg;\n\t\t\t});\n\t\t\t(window as any).rnDebug(`${name} ${type}: ${processed.join(' ')}`);\n\t\t}\n\t};\n\n\treturn {\n\t\tlogState: process.env.NODE_ENV === 'test' ? E_SDK_LOG_LEVEL.SILENT : E_SDK_LOG_LEVEL.LOG,\n\n\t\tlog(...args: any[]) {\n\t\t\tif (this.logState <= E_SDK_LOG_LEVEL.LOG) {\n\t\t\t\tconsole.log(label, ...args);\n\t\t\t\trnDebug('log', args);\n\t\t\t}\n\t\t},\n\n\t\twarn(...args: any[]) {\n\t\t\tif (this.logState <= E_SDK_LOG_LEVEL.WARN) {\n\t\t\t\tconsole.warn(label, ...args);\n\t\t\t\trnDebug('warn', args);\n\t\t\t}\n\t\t},\n\n\t\terror(...args: any[]) {\n\t\t\tif (this.logState <= E_SDK_LOG_LEVEL.ERROR) {\n\t\t\t\tconsole.error(label, ...args);\n\n\t\t\t\trnDebug('error', args);\n\t\t\t}\n\t\t},\n\n\t\t// It's a bit tricky to prepend [MappedinJs] to assert and time because of how the output is structured in the console, so it is left out for simplicity\n\t\tassert(...args: any[]) {\n\t\t\tconsole.assert(...args);\n\t\t},\n\n\t\ttime(label: string) {\n\t\t\tconsole.time(label);\n\t\t},\n\n\t\ttimeEnd(label: string) {\n\t\t\tconsole.timeEnd(label);\n\t\t},\n\t\tsetLevel(level: E_SDK_LOG_LEVEL) {\n\t\t\tif (E_SDK_LOG_LEVEL.LOG <= level && level <= E_SDK_LOG_LEVEL.SILENT) {\n\t\t\t\tthis.logState = level;\n\t\t\t}\n\t\t},\n\t};\n}\n\nconst Logger = createLogger();\nexport function setLoggerLevel(level: E_SDK_LOG_LEVEL) {\n\tif (E_SDK_LOG_LEVEL.LOG <= level && level <= E_SDK_LOG_LEVEL.SILENT) {\n\t\tLogger.logState = level;\n\t}\n}\n\nexport default Logger;\n", "import Logger from './Mappedin.Logger';\n\n/**\n * Clamp a number between lower and upper bounds with a warning\n */\nexport function clampWithWarning(x: number, lower: number, upper: number, warning: string) {\n\tif (x < lower || x > upper) {\n\t\tLogger.warn(warning);\n\t}\n\n\treturn Math.min(upper, Math.max(lower, x));\n}\n", "import { createLogger } from '../../packages/common/Mappedin.Logger';\n\nexport const Logger = createLogger('', { prefix: '[DynamicFocus]' });\n", "import type { FloorStack, MapView } from '@mappedin/mappedin-js';\nimport { Logger } from './logger';\nimport type { Building } from './building';\n\nexport class Outdoors {\n\t__type = 'outdoors';\n\t#floorStack: FloorStack;\n\t#mapView: MapView;\n\n\tconstructor(floorStack: FloorStack, mapView: MapView) {\n\t\tthis.#floorStack = floorStack;\n\t\tthis.#mapView = mapView;\n\t}\n\n\tget id() {\n\t\treturn this.#floorStack.id;\n\t}\n\n\tget floorStack() {\n\t\treturn this.#floorStack;\n\t}\n\n\tget floor() {\n\t\t// outdoors should only have 1 floor\n\t\treturn this.#floorStack.defaultFloor;\n\t}\n\n\tmatchesFloorStack(floorStack: FloorStack | string) {\n\t\treturn floorStack === this.#floorStack || floorStack === this.#floorStack.id;\n\t}\n\n\t#setVisible(visible: boolean) {\n\t\tfor (const floor of this.#floorStack.floors) {\n\t\t\tthis.#mapView.updateState(floor, {\n\t\t\t\tvisible,\n\t\t\t});\n\t\t}\n\t}\n\n\tshow() {\n\t\tthis.#setVisible(true);\n\t}\n\n\thide() {\n\t\tthis.#setVisible(false);\n\t}\n\n\tdestroy() {\n\t\tif (!this.matchesFloorStack(this.#mapView.currentFloorStack)) {\n\t\t\tthis.hide();\n\t\t}\n\t}\n}\n\nexport function getOutdoorFloorStack(floorStacks: FloorStack[], buildingsSet: Map<string, Building>): FloorStack {\n\tconst outdoorFloorStack = floorStacks.find(floorStack => floorStack.type?.toLowerCase() === 'outdoor');\n\n\tif (outdoorFloorStack) {\n\t\treturn outdoorFloorStack;\n\t}\n\n\t// If no outdoor type found, find the first floor stack that does not have a facade or is already in the buildings set\n\tconst likelyOutdoorFloorStack = floorStacks.find(\n\t\tfloorStack => floorStack.facade == null && !buildingsSet.has(floorStack.id),\n\t);\n\n\tif (likelyOutdoorFloorStack) {\n\t\treturn likelyOutdoorFloorStack;\n\t}\n\n\tLogger.warn('No good candidate for the outdoor floor stack was found. Using the first floor stack.');\n\n\treturn floorStacks[0];\n}\n", "import { getMultiFloorState } from '@mappedin/mappedin-js';\nimport type { RequiredDeep } from 'type-fest';\nimport type { DynamicFocusState } from './types';\n\nexport const DEFAULT_STATE: RequiredDeep<DynamicFocusState> = {\n\tindoorZoomThreshold: 18,\n\toutdoorZoomThreshold: 17,\n\tsetFloorOnFocus: true,\n\tautoFocus: false,\n\tindoorAnimationOptions: {\n\t\tduration: 150,\n\t},\n\toutdoorAnimationOptions: {\n\t\tduration: 150,\n\t},\n\tautoAdjustFacadeHeights: false,\n\tmode: 'default-floor',\n\tpreloadFloors: true,\n\tcustomMultiFloorVisibilityState: getMultiFloorState,\n\tdynamicBuildingInteriors: true,\n};\n"],
5
+ "mappings": "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",
6
6
  "names": ["index_exports", "__export", "DynamicFocus", "import_mappedin_js", "arraysEqual", "arr1", "arr2", "i", "__name", "_PubSub", "__publicField", "eventName", "data", "fn", "itemIdx", "__name", "PubSub", "import_mappedin_js", "_floorStack", "_floorsById", "_floorsByElevation", "_floorsByElevationSorted", "_mapView", "_animationInProgress", "_maxElevation", "_minElevation", "_Building", "floorStack", "mapView", "__publicField", "__privateAdd", "__privateSet", "floor", "__privateGet", "a", "b", "sortedSpaces", "space", "idx", "state", "f", "elevation", "targetElevation", "exactMatch", "i", "newState", "options", "currentState", "opacity", "visible", "result", "__name", "Building", "getZoomState", "zoomLevel", "indoorThreshold", "outdoorThreshold", "__name", "getFloorToShow", "target", "mode", "elevation", "building", "getFacadeState", "facade", "inFocus", "getSingleBuildingState", "floorStack", "currentFloor", "f", "visible", "getOutdoorOpacity", "floorStackStates", "state", "getSetFloorTargetFromZoomState", "buildings", "outdoors", "zoomState", "getBuildingStates", "inViewSet", "floorIdsInNavigation", "floorStackIdsInNavigation", "multiFloorView", "getMultiFloorState", "dynamicBuildingInteriors", "buildingStates", "inCameraView", "showIndoor", "shouldShowIndoor", "floorToShow", "floorStackState", "facadeState", "getBuildingAnimationType", "inRange", "inNavigation", "shouldDeferSetFloor", "trackedCameraElevation", "currentCameraElevation", "userInteracting", "DYNAMIC_FOCUS_MODES", "import_mappedin_js", "MI_ERROR_LABEL", "createLogger", "name", "prefix", "MI_ERROR_LABEL", "label", "rnDebug", "__name", "type", "args", "processed", "arg", "level", "Logger", "Mappedin_Logger_default", "Logger", "clampWithWarning", "x", "lower", "upper", "warning", "Mappedin_Logger_default", "__name", "validateFloorForStack", "floor", "floorStack", "Mappedin_Logger_default", "__name", "validateZoomThreshold", "value", "min", "max", "name", "clampWithWarning", "Logger", "createLogger", "_floorStack", "_mapView", "_Outdoors_instances", "setVisible_fn", "_Outdoors", "floorStack", "mapView", "__privateAdd", "__publicField", "__privateSet", "__privateGet", "__privateMethod", "__name", "visible", "floor", "Outdoors", "getOutdoorFloorStack", "floorStacks", "buildingsSet", "outdoorFloorStack", "likelyOutdoorFloorStack", "Logger", "import_mappedin_js", "DEFAULT_STATE", "_pubsub", "_mapView", "_mapData", "_state", "_sortedBuildingsInView", "_buildingIdsInViewSet", "_buildings", "_outdoors", "_userInteracting", "_pendingFacadeUpdate", "_floorElevation", "_cameraElevation", "_zoomState", "_viewState", "_facadesInFocus", "_enabled", "_DynamicFocus_instances", "handleViewStateChange_fn", "preloadFloors_fn", "_handleFacadesInViewChange", "_handleFloorChangeStart", "_handleUserInteractionStart", "_handleUserInteractionEnd", "_handleCameraChange", "updateFloorVisibility_fn", "animateIndoorSequence_fn", "animateOutdoorSequence_fn", "_applyBuildingStates", "_DynamicFocus", "mapView", "__privateAdd", "DEFAULT_STATE", "__publicField", "__name", "eventName", "fn", "__privateGet", "event", "facades", "arraysEqual", "__privateSet", "facade", "building", "newFloor", "altitude", "zoomLevel", "newZoomState", "getZoomState", "currentFloor", "multiFloorView", "floorIdsInNavigation", "f", "floorStackIdsInNavigation", "fs", "updatePromise", "resolve", "buildingStates", "getBuildingStates", "floorStackStates", "buildingState", "showIndoor", "floorStackState", "facadeState", "inFocus", "animation", "getBuildingAnimationType", "__privateMethod", "getOutdoorOpacity", "PubSub", "Logger", "Mappedin_Logger_default", "Building", "Outdoors", "getOutdoorFloorStack", "options", "state", "shouldReapplyBuildingStates", "validateZoomThreshold", "DYNAMIC_FOCUS_MODES", "value", "setFloor", "shouldDeferSetFloor", "target", "getSetFloorTargetFromZoomState", "floor", "getFloorToShow", "floorStack", "validateFloorForStack", "excluded", "excludedFloorStacks", "included", "includedFloorStacks", "mode", "floorStates", "shouldShow", "floorState", "result", "shouldShowIndoor", "DynamicFocus"]
7
7
  }
@@ -2,7 +2,7 @@ var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
3
 
4
4
  // <define:process>
5
- var define_process_default = { env: { npm_package_version: "6.0.1-beta.59" } };
5
+ var define_process_default = { env: { npm_package_version: "6.0.1-beta.61" } };
6
6
 
7
7
  // src/dynamic-focus.ts
8
8
  import { Floor as Floor3, getMultiFloorState as getMultiFloorState2 } from "@mappedin/mappedin-js";
@@ -833,18 +833,20 @@ var DynamicFocus = class {
833
833
  if (state.indoorZoomThreshold != null) {
834
834
  state.indoorZoomThreshold = validateZoomThreshold(
835
835
  state.indoorZoomThreshold,
836
- this.#state.outdoorZoomThreshold,
836
+ state?.outdoorZoomThreshold ?? this.#state.outdoorZoomThreshold,
837
837
  this.#mapView.Camera.maxZoomLevel,
838
838
  "indoorZoomThreshold"
839
839
  );
840
+ shouldReapplyBuildingStates = true;
840
841
  }
841
842
  if (state.outdoorZoomThreshold != null) {
842
843
  state.outdoorZoomThreshold = validateZoomThreshold(
843
844
  state.outdoorZoomThreshold,
844
845
  this.#mapView.Camera.minZoomLevel,
845
- this.#state.indoorZoomThreshold,
846
+ state?.indoorZoomThreshold ?? this.#state.indoorZoomThreshold,
846
847
  "outdoorZoomThreshold"
847
848
  );
849
+ shouldReapplyBuildingStates = true;
848
850
  }
849
851
  if (state.mode != null) {
850
852
  state.mode = DYNAMIC_FOCUS_MODES.includes(state.mode) ? state.mode : "default-floor";
@@ -1170,4 +1172,4 @@ export {
1170
1172
  __name,
1171
1173
  DynamicFocus
1172
1174
  };
1173
- //# sourceMappingURL=chunk-NUMVRZNR.js.map
1175
+ //# sourceMappingURL=chunk-RSECYADN.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["<define:process>", "../../src/dynamic-focus.ts", "../../../packages/common/array-utils.ts", "../../../packages/common/pubsub.ts", "../../src/building.ts", "../../src/dynamic-focus-scene.ts", "../../src/types.ts", "../../src/validation.ts", "../../../packages/common/Mappedin.Logger.ts", "../../../packages/common/math-utils.ts", "../../src/logger.ts", "../../src/outdoors.ts", "../../src/constants.ts"],
4
+ "sourcesContent": ["{\"env\":{\"npm_package_version\":\"6.0.1-beta.61\"}}", "import type {\n\tCameraTransform,\n\tFacade,\n\tFloorStack,\n\tMapData,\n\tMapView,\n\tTEvents,\n\tTFloorState,\n} from '@mappedin/mappedin-js';\nimport { Floor, getMultiFloorState } from '@mappedin/mappedin-js';\nimport { arraysEqual } from '@packages/internal/common/array-utils';\nimport { PubSub } from '@packages/internal/common/pubsub';\nimport { Building } from './building';\nimport {\n\tgetFloorToShow,\n\tshouldShowIndoor,\n\tgetBuildingAnimationType,\n\tgetZoomState,\n\tgetOutdoorOpacity,\n\tgetSetFloorTargetFromZoomState,\n\tgetBuildingStates,\n\tshouldDeferSetFloor,\n} from './dynamic-focus-scene';\nimport { DYNAMIC_FOCUS_MODES } from './types';\nimport type {\n\tViewState,\n\tZoomState,\n\tBuildingFacadeState,\n\tDynamicFocusEventPayload,\n\tDynamicFocusEvents,\n\tDynamicFocusMode,\n\tDynamicFocusState,\n\tBuildingFloorStackState,\n\tInternalDynamicFocusEvents,\n} from './types';\nimport { validateFloorForStack, validateZoomThreshold } from './validation';\nimport { getOutdoorFloorStack, Outdoors } from './outdoors';\nimport { Logger } from './logger';\nimport MappedinJSLogger from '../../packages/common/Mappedin.Logger';\nimport { DEFAULT_STATE } from './constants';\nimport type { MapViewExtension } from '@packages/internal/common/extensions';\n\n/**\n * Dynamic Focus is a MapView scene manager that maintains the visibility of the outdoors\n * while fading in and out building interiors as the camera pans.\n */\nexport class DynamicFocus implements MapViewExtension<DynamicFocusState> {\n\t#pubsub: PubSub<DynamicFocusEvents & InternalDynamicFocusEvents>;\n\t#mapView: MapView;\n\t#mapData: MapData;\n\t#state: Required<DynamicFocusState> = DEFAULT_STATE;\n\t/**\n\t * The buildings that are currently in view, sorted by the order they are in the facades-in-view-change event.\n\t * While these will be within the camera view, these may not be in focus or showIndoor depending on the mode.\n\t */\n\t#sortedBuildingsInView: Building[] = [];\n\t/**\n\t * The buildings that are currently in view, as a set of building ids.\n\t */\n\t#buildingIdsInViewSet = new Set<string>();\n\t#buildings = new Map<string, Building>();\n\t#outdoors: Outdoors;\n\t#userInteracting = false;\n\t#pendingFacadeUpdate = false;\n\t#floorElevation = 0;\n\t#cameraElevation = 0;\n\t/**\n\t * Tracks the current zoom state based on camera zoom level:\n\t * - 'in-range': Camera is zoomed in enough to show indoor details (>= indoorZoomThreshold)\n\t * - 'out-of-range': Camera is zoomed out to show outdoor context (<= outdoorZoomThreshold)\n\t * - 'transition': Camera is between the two thresholds (no floor changes occur)\n\t */\n\t#zoomState: ZoomState = 'transition';\n\t#viewState: ViewState = 'outdoor';\n\t/**\n\t * The facades that are actually focused and shown (filtered by showIndoor logic)\n\t */\n\t#facadesInFocus: Facade[] = [];\n\t#enabled = false;\n\n\t/**\n\t * @internal\n\t * Used to await the current scene update before starting a new one, or when the scene is updated asynchronously by an event.\n\t */\n\tprivate sceneUpdateQueue: Promise<void> = Promise.resolve();\n\n\t/**\n\t * Creates a new instance of the Dynamic Focus controller.\n\t *\n\t * @param mapView - The {@link MapView} to attach Dynamic Focus to.\n\t * @param options - Options for configuring Dynamic Focus.\n\t *\n\t * @example\n\t * ```ts\n\t * const mapView = show3dMap(...);\n\t * const df = new DynamicFocus(mapView);\n\t * df.enable({ autoFocus: true });\n\t *\n\t * // pause the listener\n\t * df.updateState({ autoFocus: false });\n\t *\n\t * // manually trigger a focus\n\t * df.focus();\n\t * ```\n\t */\n\tconstructor(mapView: MapView) {\n\t\tthis.#pubsub = new PubSub<DynamicFocusEvents & InternalDynamicFocusEvents>();\n\t\tthis.#mapView = mapView;\n\t\tLogger.setLevel(MappedinJSLogger.logState);\n\t\tthis.#mapData = this.#mapView.getMapData();\n\t\tthis.#floorElevation = this.#mapView.currentFloor.elevation;\n\t\tthis.#cameraElevation = this.#mapView.Camera.elevation;\n\t\t// initialize the buildings\n\t\tfor (const facade of this.#mapData.getByType('facade')) {\n\t\t\tthis.#buildings.set(facade.floorStack.id, new Building(facade.floorStack, this.#mapView));\n\t\t}\n\t\tthis.#outdoors = new Outdoors(\n\t\t\tgetOutdoorFloorStack(this.#mapData.getByType('floor-stack'), this.#buildings),\n\t\t\tthis.#mapView,\n\t\t);\n\t\tthis.#mapView.on('floor-change-start', this.#handleFloorChangeStart);\n\t\tthis.#mapView.on('camera-change', this.#handleCameraChange);\n\t\tthis.#mapView.on('facades-in-view-change', this.#handleFacadesInViewChange);\n\t\tthis.#mapView.on('user-interaction-start', this.#handleUserInteractionStart);\n\t\tthis.#mapView.on('user-interaction-end', this.#handleUserInteractionEnd);\n\t}\n\n\t/**\n\t * Enables Dynamic Focus with the given options.\n\t * @param options - The options to enable Dynamic Focus with.\n\t */\n\tenable(options?: Partial<DynamicFocusState>): void {\n\t\tif (this.#enabled) {\n\t\t\tLogger.warn('enable() called on an already enabled Dynamic Focus instance.');\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#enabled = true;\n\t\tthis.#mapView.manualFloorVisibility = true;\n\t\tthis.#outdoors.show();\n\t\tthis.updateState({ ...this.#state, ...options });\n\t\t// fire the camera change event to set the initial state\n\t\tthis.#handleCameraChange({\n\t\t\tzoomLevel: this.#mapView.Camera.zoomLevel,\n\t\t\tcenter: this.#mapView.Camera.center,\n\t\t\tbearing: this.#mapView.Camera.bearing,\n\t\t\tpitch: this.#mapView.Camera.pitch,\n\t\t} as CameraTransform);\n\t\t// fire dynamic focus change to set initial state of facades\n\t\tthis.#mapView.Camera.updateFacadesInView();\n\t}\n\t/**\n\t * Disables Dynamic Focus and returns the MapView to it's previous state.\n\t */\n\tdisable(): void {\n\t\tif (!this.#enabled) {\n\t\t\tLogger.warn('disable() called on an already disabled Dynamic Focus instance.');\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#enabled = false;\n\t\tthis.#mapView.manualFloorVisibility = false;\n\t}\n\n\t/**\n\t * Returns true if Dynamic Focus is enabled.\n\t */\n\tget isEnabled(): boolean {\n\t\treturn this.#enabled;\n\t}\n\n\t/**\n\t * Returns true if the current view state is indoor.\n\t */\n\tget isIndoor() {\n\t\treturn this.#viewState === 'indoor';\n\t}\n\n\t/**\n\t * Returns true if the current view state is outdoor.\n\t */\n\tget isOutdoor() {\n\t\treturn this.#viewState === 'outdoor';\n\t}\n\n\t/**\n\t * Sets the view state to indoor, regardless of the current zoom level.\n\t */\n\tsetIndoor() {\n\t\tthis.#viewState = 'indoor';\n\t\tthis.#zoomState = 'in-range';\n\n\t\tthis.#handleViewStateChange();\n\t}\n\n\t/**\n\t * Sets the view state to outdoor, regardless of the current zoom level.\n\t */\n\tsetOutdoor() {\n\t\tthis.#viewState = 'outdoor';\n\t\tthis.#zoomState = 'out-of-range';\n\n\t\tthis.#handleViewStateChange();\n\t}\n\n\t#handleViewStateChange() {\n\t\tif (this.#state.autoFocus) {\n\t\t\t// Only set the floor if setFloorOnFocus is true and the view state changed due to a user interaction\n\t\t\t// Camera animations will not trigger a focus change until they settle.\n\t\t\tif (this.#userInteracting) {\n\t\t\t\tthis.focus();\n\t\t\t} else {\n\t\t\t\tthis.#pendingFacadeUpdate = true;\n\t\t\t}\n\t\t}\n\t\tthis.#pubsub.publish('state-change');\n\t}\n\n\t#preloadFloors(mode: DynamicFocusMode) {\n\t\tthis.#mapView.preloadFloors(\n\t\t\tthis.#mapData\n\t\t\t\t.getByType('facade')\n\t\t\t\t.map(facade => getFloorToShow(this.#buildings.get(facade.floorStack.id)!, mode, this.#floorElevation))\n\t\t\t\t.filter(f => f != null && Floor.is(f)),\n\t\t);\n\t}\n\n\t/**\n\t * Returns the facades that are currently in focus.\n\t */\n\tget focusedFacades() {\n\t\treturn [...this.#facadesInFocus];\n\t}\n\n\t/**\n\t * Subscribe to a Dynamic Focus event.\n\t */\n\ton = <EventName extends keyof DynamicFocusEvents>(\n\t\teventName: EventName,\n\t\tfn: (payload: DynamicFocusEventPayload<EventName>) => void,\n\t) => {\n\t\tthis.#pubsub.on(eventName, fn);\n\t};\n\n\t/**\n\t * Unsubscribe from a Dynamic Focus event.\n\t */\n\toff = <EventName extends keyof DynamicFocusEvents>(\n\t\teventName: EventName,\n\t\tfn: (payload: DynamicFocusEventPayload<EventName>) => void,\n\t) => {\n\t\tthis.#pubsub.off(eventName, fn);\n\t};\n\n\t/**\n\t * Returns the current state of the Dynamic Focus controller.\n\t */\n\tgetState(): DynamicFocusState {\n\t\treturn { ...this.#state };\n\t}\n\n\t/**\n\t * Updates the state of the Dynamic Focus controller.\n\t * @param state - The state to update.\n\t */\n\tupdateState(state: Partial<DynamicFocusState>) {\n\t\tlet shouldReapplyBuildingStates = false;\n\n\t\tif (state.indoorZoomThreshold != null) {\n\t\t\tstate.indoorZoomThreshold = validateZoomThreshold(\n\t\t\t\tstate.indoorZoomThreshold,\n\t\t\t\tstate?.outdoorZoomThreshold ?? this.#state.outdoorZoomThreshold,\n\t\t\t\tthis.#mapView.Camera.maxZoomLevel,\n\t\t\t\t'indoorZoomThreshold',\n\t\t\t);\n\t\t\tshouldReapplyBuildingStates = true;\n\t\t}\n\t\tif (state.outdoorZoomThreshold != null) {\n\t\t\tstate.outdoorZoomThreshold = validateZoomThreshold(\n\t\t\t\tstate.outdoorZoomThreshold,\n\t\t\t\tthis.#mapView.Camera.minZoomLevel,\n\t\t\t\tstate?.indoorZoomThreshold ?? this.#state.indoorZoomThreshold,\n\t\t\t\t'outdoorZoomThreshold',\n\t\t\t);\n\t\t\tshouldReapplyBuildingStates = true;\n\t\t}\n\n\t\tif (state.mode != null) {\n\t\t\tstate.mode = DYNAMIC_FOCUS_MODES.includes(state.mode) ? state.mode : 'default-floor';\n\t\t}\n\n\t\tif (state.autoAdjustFacadeHeights != null) {\n\t\t\tthis.#state.autoAdjustFacadeHeights = state.autoAdjustFacadeHeights;\n\t\t}\n\n\t\tif (\n\t\t\tstate.dynamicBuildingInteriors != null &&\n\t\t\tstate.dynamicBuildingInteriors !== this.#state.dynamicBuildingInteriors\n\t\t) {\n\t\t\tshouldReapplyBuildingStates = true;\n\t\t}\n\n\t\t// assign state and ignore undefined values\n\t\tthis.#state = Object.assign(\n\t\t\t{},\n\t\t\tthis.#state,\n\t\t\tObject.fromEntries(Object.entries(state).filter(([, value]) => value != null)),\n\t\t);\n\n\t\t// preload the initial floors that will be included in the mode\n\t\tif (state.mode != null && state.preloadFloors) {\n\t\t\tthis.#preloadFloors(state.mode);\n\t\t}\n\n\t\tif (shouldReapplyBuildingStates) {\n\t\t\tthis.#applyBuildingStates();\n\t\t}\n\t}\n\n\t/**\n\t * Destroys the Dynamic Focus instance and unsubscribes all MapView event listeners.\n\t */\n\tdestroy() {\n\t\tthis.disable();\n\t\tthis.#mapView.off('facades-in-view-change', this.#handleFacadesInViewChange);\n\t\tthis.#mapView.off('floor-change-start', this.#handleFloorChangeStart);\n\t\tthis.#mapView.off('camera-change', this.#handleCameraChange);\n\t\tthis.#mapView.off('user-interaction-start', this.#handleUserInteractionStart);\n\t\tthis.#mapView.off('user-interaction-end', this.#handleUserInteractionEnd);\n\t\tthis.#buildings.forEach(building => building.destroy());\n\t\tthis.#outdoors.destroy();\n\t\tthis.#pubsub.destroy();\n\t}\n\n\t/**\n\t * Perform a manual visual update of the focused facades, and optionally set the floor.\n\t * @param setFloor - Whether to set the floor. This will default to the current state of setFloorOnFocus.\n\t */\n\tasync focus(setFloor = this.#state.setFloorOnFocus) {\n\t\tif (setFloor) {\n\t\t\tif (shouldDeferSetFloor(this.#cameraElevation, this.#mapView.Camera.elevation, this.#userInteracting)) {\n\t\t\t\tthis.#cameraElevation = this.#mapView.Camera.elevation;\n\t\t\t\tthis.#pendingFacadeUpdate = true;\n\t\t\t} else {\n\t\t\t\tconst target = getSetFloorTargetFromZoomState(this.#sortedBuildingsInView, this.#outdoors, this.#zoomState);\n\n\t\t\t\tconst floor = target ? getFloorToShow(target, this.#state.mode, this.#floorElevation) : undefined;\n\n\t\t\t\tif (floor && floor.id !== this.#mapView.currentFloor.id) {\n\t\t\t\t\tthis.#mapView.setFloor(floor, { context: 'dynamic-focus' });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tawait this.#applyBuildingStates();\n\t\t// must publish after the scene is updated to ensure the focusedFacades array is up to date\n\t\tthis.#pubsub.publish('focus', { facades: this.focusedFacades });\n\t}\n\n\t/**\n\t * Preloads the initial floors for each building to improve performance when rendering the building for the first time. See {@link DynamicFocusState.preloadFloors}.\n\t */\n\tpreloadFloors() {\n\t\tthis.#preloadFloors(this.#state.mode);\n\t}\n\n\t/**\n\t * Sets the default floor for a floor stack. This is the floor that will be shown when focusing on a facade if there is no currently active floor in the stack.\n\t * See {@link resetDefaultFloorForStack} to reset the default floor.\n\t * @param floorStack - The floor stack to set the default floor for.\n\t * @param floor - The floor to set as the default floor.\n\t */\n\tsetDefaultFloorForStack(floorStack: FloorStack, floor: Floor) {\n\t\tif (!validateFloorForStack(floor, floorStack)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst building = this.#buildings.get(floorStack.id);\n\t\tif (building) {\n\t\t\tbuilding.defaultFloor = floor;\n\t\t}\n\t}\n\n\t/**\n\t * Resets the default floor for a floor stack to it's initial value.\n\t * @param floorStack - The floor stack to reset the default floor for.\n\t */\n\tresetDefaultFloorForStack(floorStack: FloorStack) {\n\t\tconst building = this.#buildings.get(floorStack.id);\n\t\tif (building) {\n\t\t\tbuilding.defaultFloor = floorStack.defaultFloor;\n\t\t}\n\t}\n\n\t/**\n\t * Returns the current default floor for a floor stack.\n\t * @param floorStack - The floor stack to get the default floor for.\n\t * @returns The current default floor for the floor stack.\n\t */\n\tgetDefaultFloorForStack(floorStack: FloorStack) {\n\t\treturn this.#buildings.get(floorStack.id)?.defaultFloor || floorStack.defaultFloor || floorStack.floors[0];\n\t}\n\n\t/**\n\t * Sets the current floor for a floor stack. If the floor stack is currently focused, this floor will become visible.\n\t * @param floorStack - The floor stack to set the current floor for.\n\t */\n\tsetCurrentFloorForStack(floorStack: FloorStack, floor: Floor) {\n\t\tif (!validateFloorForStack(floor, floorStack)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst building = this.#buildings.get(floorStack.id);\n\t\tif (building) {\n\t\t\tbuilding.activeFloor = floor;\n\t\t\tthis.#applyBuildingStates();\n\t\t}\n\t}\n\n\t/**\n\t * Excludes a floor stack from visibility changes.\n\t * @param excluded - The floor stack or stacks to exclude.\n\t */\n\texclude(excluded: FloorStack | FloorStack[]) {\n\t\tconst excludedFloorStacks = Array.isArray(excluded) ? excluded : [excluded];\n\t\tfor (const floorStack of excludedFloorStacks) {\n\t\t\tconst building = this.#buildings.get(floorStack.id);\n\t\t\tif (building) {\n\t\t\t\tbuilding.excluded = true;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Includes a floor stack in visibility changes.\n\t * @param included - The floor stack or stacks to include.\n\t */\n\tinclude(included: FloorStack | FloorStack[]) {\n\t\tconst includedFloorStacks = Array.isArray(included) ? included : [included];\n\t\tfor (const floorStack of includedFloorStacks) {\n\t\t\tconst building = this.#buildings.get(floorStack.id);\n\t\t\tif (building) {\n\t\t\t\tbuilding.excluded = false;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Returns the current floor for a floor stack.\n\t * @param floorStack - The floor stack to get the current floor for.\n\t * @returns The current floor for the floor stack.\n\t */\n\tgetCurrentFloorForStack(floorStack: FloorStack) {\n\t\treturn this.#buildings.get(floorStack.id)?.activeFloor || this.getDefaultFloorForStack(floorStack);\n\t}\n\n\t/**\n\t * Handles management of focused facades but doesn't trigger view updates unless enabled.\n\t * @see {@link focus} to manually trigger a view update.\n\t */\n\t#handleFacadesInViewChange = (event: TEvents['facades-in-view-change']) => {\n\t\tif (!this.isEnabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { facades } = event;\n\n\t\t// if the facades are the same, or we're in between outdoor/indoor, don't do anything unless we're pending a facade update\n\t\tif (arraysEqual(facades, this.focusedFacades) && this.#viewState === 'transition' && !this.#pendingFacadeUpdate) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#pendingFacadeUpdate = false;\n\n\t\tthis.#sortedBuildingsInView = [];\n\t\tthis.#buildingIdsInViewSet.clear();\n\t\tif (facades.length > 0) {\n\t\t\tfor (const facade of facades) {\n\t\t\t\tconst building = this.#buildings.get(facade.floorStack.id);\n\t\t\t\tif (building) {\n\t\t\t\t\tthis.#buildingIdsInViewSet.add(building.id);\n\t\t\t\t\tthis.#sortedBuildingsInView.push(building);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.#state.autoFocus) {\n\t\t\tthis.focus();\n\t\t}\n\t};\n\t/**\n\t * Handles floor and facade visibility when the floor changes.\n\t */\n\t#handleFloorChangeStart = async (event: TEvents['floor-change-start']) => {\n\t\tif (!this.isEnabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { floor: newFloor } = event;\n\t\tconst building = this.#buildings.get(newFloor.floorStack.id);\n\t\tif (building) {\n\t\t\tbuilding.activeFloor = newFloor;\n\t\t}\n\t\t// Don't update elevation when switching to outdoor floor stack\n\t\tif (building?.excluded === false && !this.#outdoors.matchesFloorStack(newFloor.floorStack)) {\n\t\t\tthis.#floorElevation = newFloor.elevation;\n\t\t}\n\n\t\tif (this.#mapView.manualFloorVisibility === true) {\n\t\t\tif (event.reason !== 'dynamic-focus') {\n\t\t\t\tawait this.#applyBuildingStates(newFloor);\n\t\t\t\t// Despite this not really being a focus event, we've changed the focused facades, so we need to publish it\n\t\t\t\tthis.#pubsub.publish('focus', { facades: this.focusedFacades });\n\t\t\t}\n\n\t\t\tconst altitude = building?.floorsAltitudesMap.get(newFloor.elevation)?.altitude ?? 0;\n\t\t\tif (\n\t\t\t\tthis.#mapView.options.multiFloorView != null &&\n\t\t\t\tthis.#mapView.options.multiFloorView?.enabled &&\n\t\t\t\tthis.#mapView.options.multiFloorView?.updateCameraElevationOnFloorChange &&\n\t\t\t\tthis.#mapView.Camera.elevation !== altitude\n\t\t\t) {\n\t\t\t\tthis.#mapView.Camera.animateElevation(altitude, {\n\t\t\t\t\tduration: 750,\n\t\t\t\t\teasing: 'ease-in-out',\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t};\n\n\t#handleUserInteractionStart = () => {\n\t\tthis.#userInteracting = true;\n\t};\n\t#handleUserInteractionEnd = () => {\n\t\tthis.#userInteracting = false;\n\t};\n\n\t/**\n\t * Handles camera moving in and out of zoom range and fires a focus event if the camera is in range.\n\t */\n\t#handleCameraChange = (event: TEvents['camera-change']) => {\n\t\tif (!this.isEnabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { zoomLevel } = event;\n\t\tconst newZoomState = getZoomState(zoomLevel, this.#state.indoorZoomThreshold, this.#state.outdoorZoomThreshold);\n\n\t\tif (this.#zoomState !== newZoomState) {\n\t\t\tthis.#zoomState = newZoomState;\n\n\t\t\tif (newZoomState === 'in-range') {\n\t\t\t\tthis.setIndoor();\n\t\t\t} else if (newZoomState === 'out-of-range') {\n\t\t\t\tthis.setOutdoor();\n\t\t\t}\n\t\t}\n\t};\n\n\t#updateFloorVisibility(floorStates: BuildingFloorStackState['floorStates'], shouldShow: boolean, inFocus?: boolean) {\n\t\tfloorStates.forEach(floorState => {\n\t\t\tif (floorState.floor) {\n\t\t\t\tif (shouldShow) {\n\t\t\t\t\tconst state =\n\t\t\t\t\t\tinFocus !== undefined\n\t\t\t\t\t\t\t? ({\n\t\t\t\t\t\t\t\t\t...floorState.state,\n\t\t\t\t\t\t\t\t\tlabels: {\n\t\t\t\t\t\t\t\t\t\t...floorState.state.labels,\n\t\t\t\t\t\t\t\t\t\tenabled: floorState.state.labels.enabled && inFocus,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tmarkers: {\n\t\t\t\t\t\t\t\t\t\t...floorState.state.markers,\n\t\t\t\t\t\t\t\t\t\tenabled: floorState.state.markers.enabled && inFocus,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tocclusion: {\n\t\t\t\t\t\t\t\t\t\t...floorState.state.occlusion,\n\t\t\t\t\t\t\t\t\t\t// We don't want this floor to occlude if it's not in focus\n\t\t\t\t\t\t\t\t\t\t// Allows us to show a label above this floor while it's not active\n\t\t\t\t\t\t\t\t\t\tenabled: floorState.state.occlusion.enabled && inFocus,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t } satisfies TFloorState)\n\t\t\t\t\t\t\t: floorState.state;\n\n\t\t\t\t\tthis.#mapView.updateState(floorState.floor, state);\n\t\t\t\t} else {\n\t\t\t\t\tthis.#mapView.updateState(floorState.floor, { visible: false });\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tasync #animateIndoorSequence(\n\t\tbuilding: Building,\n\t\tfloorStackState: BuildingFloorStackState,\n\t\tfacadeState: BuildingFacadeState,\n\t\tinFocus: boolean,\n\t) {\n\t\t// show floor first then fade in the facade\n\t\tthis.#updateFloorVisibility(floorStackState.floorStates, true, inFocus);\n\n\t\treturn building.animateFacade(facadeState.state, this.#state.indoorAnimationOptions);\n\t}\n\n\tasync #animateOutdoorSequence(\n\t\tbuilding: Building,\n\t\tfloorStackState: BuildingFloorStackState,\n\t\tfacadeState: BuildingFacadeState,\n\t\tfloorStackIdsInNavigation: string[],\n\t) {\n\t\t// fade in facade then hide floors when complete\n\t\tconst result = await building.animateFacade(facadeState.state, this.#state.outdoorAnimationOptions);\n\n\t\tif (result.result === 'completed') {\n\t\t\t// Re-check if we should still show indoor after animation completes\n\t\t\tthis.#updateFloorVisibility(\n\t\t\t\tfloorStackState.floorStates,\n\t\t\t\tshouldShowIndoor(\n\t\t\t\t\tbuilding,\n\t\t\t\t\tthis.#mapView.currentFloor,\n\t\t\t\t\tthis.#zoomState === 'in-range',\n\t\t\t\t\tthis.#buildingIdsInViewSet.has(building.id),\n\t\t\t\t\tthis.#state.mode,\n\t\t\t\t\tthis.#floorElevation,\n\t\t\t\t\tfloorStackIdsInNavigation.includes(building.floorStack.id),\n\t\t\t\t\tthis.#state.dynamicBuildingInteriors,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t#applyBuildingStates = async (newFloor?: Floor) => {\n\t\tif (this.#mapView.manualFloorVisibility !== true || !this.isEnabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentFloor = newFloor || this.#mapView.currentFloor;\n\t\tconst multiFloorView = this.#mapView.options.multiFloorView;\n\t\tconst floorIdsInNavigation = this.#mapView.Navigation?.floors?.map(f => f.id) || [];\n\t\tconst floorStackIdsInNavigation = this.#mapView.Navigation?.floorStacks.map(fs => fs.id) || [];\n\n\t\t// Create a new promise for this update\n\t\tconst updatePromise = new Promise<void>(async resolve => {\n\t\t\t// Wait for the previous update to complete\n\t\t\tawait this.sceneUpdateQueue;\n\n\t\t\tconst buildingStates = getBuildingStates(\n\t\t\t\tArray.from(this.#buildings.values()),\n\t\t\t\tthis.#buildingIdsInViewSet,\n\t\t\t\tcurrentFloor,\n\t\t\t\tthis.#zoomState,\n\t\t\t\tthis.#state.mode,\n\t\t\t\tthis.#floorElevation,\n\t\t\t\tfloorIdsInNavigation,\n\t\t\t\tfloorStackIdsInNavigation,\n\t\t\t\tmultiFloorView,\n\t\t\t\tthis.#state.customMultiFloorVisibilityState ?? getMultiFloorState,\n\t\t\t\tthis.#state.dynamicBuildingInteriors,\n\t\t\t);\n\n\t\t\tconst floorStackStates: BuildingFloorStackState[] = [];\n\t\t\tawait Promise.all(\n\t\t\t\tArray.from(buildingStates.values()).map(async buildingState => {\n\t\t\t\t\tconst { building, showIndoor, floorStackState, facadeState, inFocus } = buildingState;\n\n\t\t\t\t\tfloorStackStates.push(floorStackState);\n\n\t\t\t\t\tconst animation = getBuildingAnimationType(building, showIndoor);\n\n\t\t\t\t\tif (animation === 'indoor') {\n\t\t\t\t\t\treturn this.#animateIndoorSequence(building, floorStackState, facadeState, inFocus);\n\t\t\t\t\t} else if (animation === 'outdoor') {\n\t\t\t\t\t\treturn this.#animateOutdoorSequence(building, floorStackState, facadeState, floorStackIdsInNavigation);\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t);\n\n\t\t\tthis.#mapView.Outdoor.setOpacity(getOutdoorOpacity(floorStackStates, this.#state.mode));\n\n\t\t\t// Filter #facadesInFocus to maintain sort order, keeping only buildings with showIndoor true\n\t\t\tthis.#facadesInFocus = this.#sortedBuildingsInView\n\t\t\t\t.filter(building => buildingStates.get(building.id)?.showIndoor === true)\n\t\t\t\t.map(building => building.facade);\n\n\t\t\tthis.#pubsub.publish('focus', { facades: this.#facadesInFocus });\n\n\t\t\tresolve();\n\t\t});\n\n\t\t// Update the queue with the new promise\n\t\tthis.sceneUpdateQueue = updatePromise;\n\n\t\treturn updatePromise;\n\t};\n}\n", "/**\n * Compare two arrays for equality\n */\nexport function arraysEqual(arr1: any[] | null | undefined, arr2: any[] | null | undefined) {\n\tif (arr1 == null || arr2 == null) {\n\t\treturn arr1 === arr2;\n\t}\n\n\tif (arr1.length !== arr2.length) {\n\t\treturn false;\n\t}\n\n\tfor (let i = 0; i < arr1.length; i++) {\n\t\tif (arr1[i] !== arr2[i]) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n", "/**\n * Generic PubSub class implementing the Publish-Subscribe pattern for event handling.\n *\n * @template EVENT_PAYLOAD - The type of the event payload.\n * @template EVENT - The type of the event.\n */\nexport class PubSub<EVENT_PAYLOAD, EVENT extends keyof EVENT_PAYLOAD = keyof EVENT_PAYLOAD> {\n\t/**\n\t * @private\n\t * @internal\n\t */\n\tprivate _subscribers: any = {};\n\t/**\n\t * @private\n\t * @internal\n\t */\n\tprivate _destroyed = false;\n\n\t/**\n\t * @private\n\t * @internal\n\t */\n\tpublish<EVENT_NAME extends EVENT>(eventName: EVENT_NAME, data?: EVENT_PAYLOAD[EVENT_NAME]) {\n\t\tif (!this._subscribers || !this._subscribers[eventName] || this._destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._subscribers[eventName]!.forEach(function (fn) {\n\t\t\tif (typeof fn !== 'function') {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfn(data);\n\t\t});\n\t}\n\n\t/**\n\t * Subscribe a function to an event.\n\t *\n\t * @param eventName An event name which, when fired, will call the provided\n\t * function.\n\t * @param fn A callback that gets called when the corresponding event is fired. The\n\t * callback will get passed an argument with a type that's one of event payloads.\n\t * @example\n\t * // Subscribe to the 'click' event\n\t * const handler = (event) => {\n\t * const { coordinate } = event;\n\t * const { latitude, longitude } = coordinate;\n\t * \tconsole.log(`Map was clicked at ${latitude}, ${longitude}`);\n\t * };\n\t * map.on('click', handler);\n\t */\n\ton<EVENT_NAME extends EVENT>(\n\t\teventName: EVENT_NAME,\n\t\tfn: (\n\t\t\tpayload: EVENT_PAYLOAD[EVENT_NAME] extends {\n\t\t\t\tdata: null;\n\t\t\t}\n\t\t\t\t? EVENT_PAYLOAD[EVENT_NAME]['data']\n\t\t\t\t: EVENT_PAYLOAD[EVENT_NAME],\n\t\t) => void,\n\t) {\n\t\tif (!this._subscribers || this._destroyed) {\n\t\t\tthis._subscribers = {};\n\t\t}\n\t\tthis._subscribers[eventName] = this._subscribers[eventName] || [];\n\t\tthis._subscribers[eventName]!.push(fn);\n\t}\n\n\t/**\n\t * Unsubscribe a function previously subscribed with {@link on}\n\t *\n\t * @param eventName An event name to which the provided function was previously\n\t * subscribed.\n\t * @param fn A function that was previously passed to {@link on}. The function must\n\t * have the same reference as the function that was subscribed.\n\t * @example\n\t * // Unsubscribe from the 'click' event\n\t * const handler = (event) => {\n\t * \tconsole.log('Map was clicked', event);\n\t * };\n\t * map.off('click', handler);\n\t */\n\toff<EVENT_NAME extends EVENT>(\n\t\teventName: EVENT_NAME,\n\t\tfn: (\n\t\t\tpayload: EVENT_PAYLOAD[EVENT_NAME] extends {\n\t\t\t\tdata: null;\n\t\t\t}\n\t\t\t\t? EVENT_PAYLOAD[EVENT_NAME]['data']\n\t\t\t\t: EVENT_PAYLOAD[EVENT_NAME],\n\t\t) => void,\n\t) {\n\t\tif (!this._subscribers || this._subscribers[eventName] == null || this._destroyed) {\n\t\t\treturn;\n\t\t}\n\t\tconst itemIdx = this._subscribers[eventName]!.indexOf(fn);\n\n\t\tif (itemIdx !== -1) {\n\t\t\tthis._subscribers[eventName]!.splice(itemIdx, 1);\n\t\t}\n\t}\n\t/**\n\t * @private\n\t * @internal\n\t */\n\tdestroy() {\n\t\tthis._destroyed = true;\n\t\tthis._subscribers = {};\n\t}\n}\n", "import type { MapView, TAnimateStateResult, TFacadeState } from '@mappedin/mappedin-js';\nimport { Facade, Floor, FloorStack } from '@mappedin/mappedin-js';\nimport type { DynamicFocusAnimationOptions } from './types';\n\nexport class Building {\n\t__type = 'building';\n\t#floorStack: FloorStack;\n\t#floorsById = new Map<string, Floor>();\n\t#floorsByElevation = new Map<number, Floor>();\n\t#floorsByElevationSorted: Floor[] = [];\n\t#mapView: MapView;\n\t#animationInProgress: { state: TFacadeState; animation: ReturnType<MapView['animateState']> } | undefined;\n\n\tdefaultFloor: Floor;\n\tactiveFloor: Floor;\n\texcluded = false;\n\tfloorsAltitudesMap: Map<number, { altitude: number; effectiveHeight: number }> = new Map();\n\taboveGroundFloors: Floor[] = [];\n\n\tconstructor(floorStack: FloorStack, mapView: MapView) {\n\t\tthis.#floorStack = floorStack;\n\t\tthis.#floorsById = new Map(floorStack.floors.map(floor => [floor.id, floor]));\n\t\tthis.#floorsByElevation = new Map(floorStack.floors.map(floor => [floor.elevation, floor]));\n\t\tthis.#floorsByElevationSorted = Array.from(this.#floorsByElevation.values()).sort(\n\t\t\t(a, b) => a.elevation - b.elevation,\n\t\t);\n\t\tthis.defaultFloor = floorStack.defaultFloor;\n\t\tthis.activeFloor = this.defaultFloor;\n\t\tthis.#mapView = mapView;\n\t\tthis.aboveGroundFloors = this.#floorsByElevationSorted.filter(floor => floor.elevation >= 0);\n\n\t\tconst sortedSpaces = floorStack.facade?.spaces\n\t\t\t.map(space => this.#mapView.getState(space))\n\t\t\t.sort((a, b) => a.altitude - b.altitude);\n\t\tif (sortedSpaces && sortedSpaces.length === this.aboveGroundFloors.length) {\n\t\t\tfor (const idx in this.aboveGroundFloors) {\n\t\t\t\tconst floor = this.aboveGroundFloors[idx];\n\t\t\t\tconst space = sortedSpaces[idx];\n\t\t\t\tthis.floorsAltitudesMap.set(floor.elevation, {\n\t\t\t\t\taltitude: space.altitude,\n\t\t\t\t\teffectiveHeight: space.height,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tget id() {\n\t\treturn this.#floorStack.id;\n\t}\n\n\tget name() {\n\t\treturn this.#floorStack.name;\n\t}\n\n\tget floors() {\n\t\treturn this.#floorStack.floors;\n\t}\n\n\tget floorStack() {\n\t\treturn this.#floorStack;\n\t}\n\n\tget facade() {\n\t\t// the floorstack must have a facade if we created a building for it\n\t\treturn this.#floorStack.facade!;\n\t}\n\n\tget isCurrentFloorStack() {\n\t\treturn this.id === this.#mapView.currentFloorStack.id;\n\t}\n\n\tget isIndoor() {\n\t\tconst state = this.#mapView.getState(this.facade);\n\n\t\treturn this.isCurrentFloorStack || (state?.visible === false && state?.opacity === 0);\n\t}\n\n\tget canSetFloor() {\n\t\treturn this.isIndoor || !this.excluded;\n\t}\n\n\t#maxElevation: number | undefined;\n\tget maxElevation() {\n\t\tif (this.#maxElevation == null) {\n\t\t\tthis.#maxElevation = Math.max(...this.#floorsByElevation.keys());\n\t\t}\n\n\t\treturn this.#maxElevation;\n\t}\n\n\t#minElevation: number | undefined;\n\tget minElevation() {\n\t\tif (this.#minElevation == null) {\n\t\t\tthis.#minElevation = Math.min(...this.#floorsByElevation.keys());\n\t\t}\n\n\t\treturn this.#minElevation;\n\t}\n\n\thas(f: Floor | FloorStack | Facade) {\n\t\tif (Floor.is(f)) {\n\t\t\treturn this.#floorsById.has(f.id);\n\t\t}\n\n\t\tif (FloorStack.is(f)) {\n\t\t\treturn f.id === this.#floorStack.id;\n\t\t}\n\n\t\tif (Facade.is(f)) {\n\t\t\treturn f.id === this.facade.id;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tgetFloorByElevation(elevation: number) {\n\t\treturn this.#floorsByElevation.get(elevation);\n\t}\n\n\tgetNearestFloorByElevation(targetElevation: number): Floor | undefined {\n\t\tconst exactMatch = this.getFloorByElevation(targetElevation);\n\t\tif (exactMatch) {\n\t\t\treturn exactMatch;\n\t\t}\n\n\t\tif (targetElevation >= 0) {\n\t\t\t// For positive elevations, return highest floor if target is above max\n\t\t\tif (targetElevation > this.maxElevation) {\n\t\t\t\treturn this.#floorsByElevationSorted[this.#floorsByElevationSorted.length - 1];\n\t\t\t}\n\n\t\t\t// Search backwards from the end\n\t\t\tfor (let i = this.#floorsByElevationSorted.length - 1; i >= 0; i--) {\n\t\t\t\tconst floor = this.#floorsByElevationSorted[i];\n\t\t\t\tif (floor.elevation <= targetElevation) {\n\t\t\t\t\treturn floor;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// For negative elevations (basements), return the lowest floor if target is below min\n\t\t\tif (targetElevation < this.minElevation) {\n\t\t\t\treturn this.#floorsByElevationSorted[0];\n\t\t\t}\n\n\t\t\t// Search forwards from the start\n\t\t\tfor (const floor of this.#floorsByElevationSorted) {\n\t\t\t\tif (floor.elevation >= targetElevation) {\n\t\t\t\t\treturn floor;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\tgetHighestFloor(): Floor {\n\t\treturn this.#floorsByElevationSorted[this.#floorsByElevationSorted.length - 1];\n\t}\n\n\tcancelAnimation() {\n\t\tif (this.#animationInProgress) {\n\t\t\tthis.#animationInProgress.animation.cancel();\n\t\t\tthis.#animationInProgress = undefined;\n\t\t}\n\t}\n\n\tasync animateFacade(\n\t\tnewState: TFacadeState,\n\t\toptions: DynamicFocusAnimationOptions = { duration: 150 },\n\t): Promise<TAnimateStateResult> {\n\t\tconst currentState = this.#animationInProgress?.state || this.#mapView.getState(this.facade);\n\t\tif (\n\t\t\t!currentState ||\n\t\t\t!newState ||\n\t\t\t(currentState?.opacity === newState.opacity && currentState?.visible === newState.visible)\n\t\t) {\n\t\t\t// nothing to do\n\t\t\treturn { result: 'completed' };\n\t\t}\n\n\t\tthis.cancelAnimation();\n\t\tconst { opacity, visible } = newState;\n\n\t\t// always set facade visible so it can be seen during animation\n\t\tthis.#mapView.updateState(this.facade, {\n\t\t\tvisible: true,\n\t\t});\n\n\t\tif (opacity !== undefined) {\n\t\t\tthis.#animationInProgress = {\n\t\t\t\tanimation: this.#mapView.animateState(\n\t\t\t\t\tthis.facade,\n\t\t\t\t\t{\n\t\t\t\t\t\topacity,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tduration: options.duration,\n\t\t\t\t\t},\n\t\t\t\t),\n\t\t\t\tstate: newState,\n\t\t\t};\n\t\t\tconst result = await this.#animationInProgress.animation;\n\n\t\t\tthis.#animationInProgress = undefined;\n\n\t\t\tif (result.result === 'cancelled') {\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\n\t\tif (visible === false) {\n\t\t\tthis.#mapView.updateState(this.facade, {\n\t\t\t\tvisible,\n\t\t\t});\n\t\t}\n\n\t\treturn { result: 'completed' };\n\t}\n\n\tdestroy() {\n\t\tthis.cancelAnimation();\n\t\t// Hide all floors except current floor\n\t\tthis.#floorStack.floors.forEach(floor => {\n\t\t\tthis.#mapView.updateState(floor, {\n\t\t\t\tvisible: floor.id === this.#mapView.currentFloor.id,\n\t\t\t});\n\t\t});\n\t\t// Show the facade if the current floor is not in this building\n\t\tif (!this.has(this.#mapView.currentFloor)) {\n\t\t\tthis.#mapView.updateState(this.facade, {\n\t\t\t\tvisible: true,\n\t\t\t\topacity: 1,\n\t\t\t});\n\t\t}\n\t}\n}\n", "import type { Facade, Floor, FloorStack, TFloorState } from '@mappedin/mappedin-js';\nimport type { Building } from './building';\nimport type {\n\tBuildingAnimation,\n\tBuildingFacadeState,\n\tBuildingFloorStackState,\n\tDynamicFocusMode,\n\tMultiFloorVisibilityState,\n\tZoomState,\n} from './types';\nimport type { Outdoors } from './outdoors';\n\n/**\n * Calculates the zoom state based on camera zoom level and thresholds.\n */\nexport function getZoomState(zoomLevel: number, indoorThreshold: number, outdoorThreshold: number): ZoomState {\n\tif (zoomLevel >= indoorThreshold) {\n\t\treturn 'in-range';\n\t}\n\tif (zoomLevel <= outdoorThreshold) {\n\t\treturn 'out-of-range';\n\t}\n\n\treturn 'transition';\n}\n\nexport function getFloorToShow(\n\ttarget: Building | Outdoors,\n\tmode: DynamicFocusMode,\n\televation: number,\n): Floor | undefined {\n\tif (target.__type === 'outdoors' && 'floor' in target) {\n\t\treturn target.floor;\n\t}\n\n\tconst building = target as Building;\n\tif (building.excluded) {\n\t\treturn building.activeFloor;\n\t}\n\n\tswitch (mode) {\n\t\tcase 'lock-elevation':\n\t\t\treturn building.getFloorByElevation(elevation);\n\t\tcase 'nearest-elevation':\n\t\t\treturn building.getNearestFloorByElevation(elevation);\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\t// if the building is already showing, don't switch to the default floor\n\treturn building.isIndoor ? building.activeFloor : building.defaultFloor;\n}\n\nexport function getFacadeState(facade: Facade, inFocus: boolean): BuildingFacadeState {\n\treturn {\n\t\tfacade,\n\t\tstate: {\n\t\t\ttype: 'facade',\n\t\t\tvisible: !inFocus,\n\t\t\topacity: inFocus ? 0 : 1,\n\t\t},\n\t};\n}\n\nexport function getSingleBuildingState(\n\tfloorStack: FloorStack,\n\tcurrentFloor: Floor,\n\tinFocus: boolean,\n): BuildingFloorStackState {\n\treturn {\n\t\toutdoorOpacity: 1,\n\t\tfloorStates: floorStack.floors.map(f => {\n\t\t\tconst visible = f.id === currentFloor.id && inFocus;\n\n\t\t\treturn {\n\t\t\t\tfloor: f,\n\t\t\t\tstate: {\n\t\t\t\t\ttype: 'floor',\n\t\t\t\t\tvisible: visible,\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\tvisible: visible,\n\t\t\t\t\t},\n\t\t\t\t\tlabels: {\n\t\t\t\t\t\tenabled: visible,\n\t\t\t\t\t},\n\t\t\t\t\tmarkers: {\n\t\t\t\t\t\tenabled: visible,\n\t\t\t\t\t},\n\t\t\t\t\tfootprint: {\n\t\t\t\t\t\tvisible: false,\n\t\t\t\t\t},\n\t\t\t\t\tocclusion: {\n\t\t\t\t\t\tenabled: false,\n\t\t\t\t\t},\n\t\t\t\t} as Required<TFloorState>,\n\t\t\t};\n\t\t}),\n\t};\n}\n\n/**\n * Calculates the outdoor opacity based on floor stack states and mode.\n */\nexport function getOutdoorOpacity(floorStackStates: BuildingFloorStackState[], mode: DynamicFocusMode): number {\n\tif (!mode.includes('lock-elevation')) {\n\t\treturn 1;\n\t}\n\n\tfor (const state of floorStackStates) {\n\t\tif (state.outdoorOpacity >= 0 && state.outdoorOpacity <= 1) {\n\t\t\treturn state.outdoorOpacity;\n\t\t}\n\t}\n\n\treturn 1;\n}\n\nexport function getSetFloorTargetFromZoomState(\n\tbuildings: Building[],\n\toutdoors: Outdoors,\n\tzoomState: ZoomState,\n): Building | Outdoors | undefined {\n\tswitch (zoomState) {\n\t\tcase 'in-range':\n\t\t\treturn buildings[0]?.canSetFloor ? buildings[0] : undefined;\n\t\tcase 'out-of-range':\n\t\t\treturn outdoors;\n\t\tcase 'transition':\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n}\n\n/**\n * Gets the building states for all buildings.\n */\nexport function getBuildingStates(\n\tbuildings: Building[],\n\tinViewSet: Set<string>,\n\tcurrentFloor: Floor,\n\tzoomState: ZoomState,\n\tmode: DynamicFocusMode,\n\televation: number,\n\tfloorIdsInNavigation: string[],\n\tfloorStackIdsInNavigation: string[],\n\tmultiFloorView: any,\n\tgetMultiFloorState: MultiFloorVisibilityState,\n\tdynamicBuildingInteriors: boolean,\n): Map<\n\tstring,\n\t{\n\t\tbuilding: Building;\n\t\tshowIndoor: boolean;\n\t\tfloorStackState: BuildingFloorStackState;\n\t\tfacadeState: BuildingFacadeState;\n\t\tinFocus: boolean;\n\t\tfloorToShow: Floor | undefined;\n\t}\n> {\n\tconst buildingStates = new Map();\n\n\tfor (const building of buildings) {\n\t\tconst inCameraView = inViewSet.has(building.id);\n\t\tconst showIndoor = shouldShowIndoor(\n\t\t\tbuilding,\n\t\t\tcurrentFloor,\n\t\t\tzoomState === 'in-range',\n\t\t\tinCameraView,\n\t\t\tmode,\n\t\t\televation,\n\t\t\tfloorStackIdsInNavigation.includes(building.id),\n\t\t\tdynamicBuildingInteriors,\n\t\t);\n\n\t\tconst floorToShow =\n\t\t\tcurrentFloor.floorStack.id === building.id ? building.activeFloor : getFloorToShow(building, mode, elevation);\n\n\t\tconst floorStackState = multiFloorView.enabled\n\t\t\t? getMultiFloorState(\n\t\t\t\t\tbuilding.floors,\n\t\t\t\t\tfloorToShow || building.activeFloor,\n\t\t\t\t\tmultiFloorView?.floorGap,\n\t\t\t\t\tfloorIdsInNavigation,\n\t\t\t\t\tbuilding.floorsAltitudesMap,\n\t\t\t )\n\t\t\t: getSingleBuildingState(building.floorStack, floorToShow || building.activeFloor, showIndoor);\n\n\t\tconst facadeState = getFacadeState(building.facade, showIndoor);\n\t\tbuildingStates.set(building.id, {\n\t\t\tbuilding,\n\t\t\tshowIndoor,\n\t\t\tfloorStackState,\n\t\t\tfacadeState,\n\t\t\tinFocus: inCameraView,\n\t\t\tfloorToShow,\n\t\t});\n\t}\n\n\treturn buildingStates;\n}\n\nexport function getBuildingAnimationType(building: Building, showIndoor: boolean): BuildingAnimation {\n\tif (building.excluded) {\n\t\treturn 'none';\n\t}\n\n\tif (showIndoor) {\n\t\treturn 'indoor';\n\t}\n\n\treturn 'outdoor';\n}\n\n/**\n * Determines if a building's indoor floors should be shown through a number of different state checks.\n */\nexport function shouldShowIndoor(\n\tbuilding: Building,\n\tcurrentFloor: Floor,\n\tinRange: boolean,\n\tinFocus: boolean,\n\tmode: DynamicFocusMode,\n\televation: number,\n\tinNavigation: boolean,\n\tdynamicBuildingInteriors: boolean,\n): boolean {\n\t// always show the current floor regardless of any other states\n\tif (building.id === currentFloor.floorStack.id) {\n\t\treturn true;\n\t}\n\n\t// if the building is excluded, we don't control the visibility, so don't show it\n\tif (building.excluded) {\n\t\treturn false;\n\t}\n\n\t// if it's not excluded, always show the navigation\n\tif (inNavigation === true) {\n\t\treturn true;\n\t}\n\n\t// Without dynamic building interiors, we only rely on whether the current floor is indoor or outdoor\n\tif (!dynamicBuildingInteriors) {\n\t\treturn currentFloor.floorStack.type !== 'Outdoor';\n\t}\n\n\t// the following cases rely on the camera being in range\n\tif (!inRange) {\n\t\treturn false;\n\t}\n\n\t// the following cases rely on the building being in focus\n\tif (!inFocus) {\n\t\treturn false;\n\t}\n\n\tswitch (mode) {\n\t\tcase 'lock-elevation':\n\t\t\treturn building.getFloorByElevation(elevation) != null;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\treturn true;\n}\n\nexport function shouldDeferSetFloor(\n\ttrackedCameraElevation: number,\n\tcurrentCameraElevation: number,\n\tuserInteracting: boolean,\n): boolean {\n\treturn trackedCameraElevation !== currentCameraElevation && !userInteracting;\n}\n", "import type { Facade, Floor, TFacadeState } from '@mappedin/mappedin-js';\nimport type { VisibilityState as BuildingFloorStackState } from '../../mappedin-js/src/api-geojson/multi-floor';\n\nexport type MultiFloorVisibilityState = (\n\tfloors: Floor[],\n\tcurrentFloor: Floor,\n\tfloorGap: number,\n\tfloorIdsInNavigation: Floor['id'][],\n\tfloorsVisualHeightMap?: Map<number, { altitude: number; effectiveHeight: number }>,\n) => BuildingFloorStackState;\n\nexport type DynamicFocusAnimationOptions = {\n\t/**\n\t * The duration of the animation in milliseconds.\n\t * @default 150\n\t */\n\tduration: number;\n};\n\n/**\n * Array of valid dynamic focus modes for runtime validation.\n */\nexport const DYNAMIC_FOCUS_MODES = ['default-floor', 'lock-elevation', 'nearest-elevation'] as const;\n\n/**\n * The mode which determines the indoor floor to reveal when the camera focuses on a facade.\n * - 'default-floor' - Show the default floor of the floor stack.\n * - 'lock-elevation' - Show the floor at the current elevation, if possible.\n * When a floor stack does not have a floor at the current elevation, no indoor floor will be shown.\n * - 'nearest-elevation' - Show the floor at the current elevation, if possible.\n * When a floor stack does not have a floor at the current elevation, show the indoor floor at the nearest lower elevation.\n */\nexport type DynamicFocusMode = (typeof DYNAMIC_FOCUS_MODES)[number];\n\n/**\n * State of the Dynamic Focus controller.\n */\nexport type DynamicFocusState = {\n\t/**\n\t * Whether to automatically focus on the outdoors when the camera moves in range.\n\t * @default true\n\t */\n\tautoFocus: boolean;\n\t/**\n\t * The zoom level at which the camera will fade out the facades and fade in the indoor floors.\n\t * @default 18\n\t */\n\tindoorZoomThreshold: number;\n\t/**\n\t * The zoom level at which the camera will fade in the facades and fade out the indoor floors.\n\t * @default 17\n\t */\n\toutdoorZoomThreshold: number;\n\t/**\n\t * Whether to set the floor to the outdoors when the camera moves in range.\n\t * @default true\n\t */\n\tsetFloorOnFocus: boolean;\n\t/**\n\t * Options for the animation when fading out the facade to reveal the interior.\n\t */\n\tindoorAnimationOptions: DynamicFocusAnimationOptions;\n\t/**\n\t * Options for the animation when fading in the facade to hide the interior.\n\t */\n\toutdoorAnimationOptions: DynamicFocusAnimationOptions;\n\t/**\n\t * The mode of the Dynamic Focus controller.\n\t * @default 'default-floor'\n\t */\n\tmode: DynamicFocusMode;\n\t/**\n\t * Whether to automatically adjust facade heights to align with floor boundaries in multi-floor buildings.\n\t * @default false\n\t */\n\tautoAdjustFacadeHeights: boolean;\n\t/**\n\t * Whether to automatically hide the indoors of buildings not in or near the camera's view.\n\t * @default true\n\t */\n\tdynamicBuildingInteriors: boolean;\n\t/**\n\t * Whether to preload the geometry of the initial floors in each building. Improves performance when rendering the building for the first time.\n\t * @default true\n\t */\n\tpreloadFloors: boolean;\n\n\t/**\n\t * @experimental\n\t * @internal\n\t * A custom function to override the default floor visibility state.\n\t * This is useful for customizing the floor visibility state for a specific building.\n\t */\n\tcustomMultiFloorVisibilityState?: MultiFloorVisibilityState;\n};\n\n/**\n * Internal events emitted for updating React state.\n */\nexport type InternalDynamicFocusEvents = {\n\t'state-change': undefined;\n};\n\n/**\n * Events emitted by the Dynamic Focus controller.\n */\nexport type DynamicFocusEvents = {\n\t/**\n\t * Emitted when the Dynamic Focus controller triggers a focus update either from a camera change or manually calling `focus()`.\n\t */\n\tfocus: {\n\t\tfacades: Facade[];\n\t};\n};\n\nexport type DynamicFocusEventPayload<EventName extends keyof DynamicFocusEvents> =\n\tDynamicFocusEvents[EventName] extends { data: null }\n\t\t? DynamicFocusEvents[EventName]['data']\n\t\t: DynamicFocusEvents[EventName];\n\nexport type BuildingFacadeState = {\n\tfacade: Facade;\n\tstate: TFacadeState;\n};\n\nexport type BuildingState = BuildingFloorStackState & {\n\tfacadeState: BuildingFacadeState;\n};\n\nexport type ZoomState = 'in-range' | 'out-of-range' | 'transition';\nexport type ViewState = 'indoor' | 'outdoor' | 'transition';\n\nexport type BuildingAnimation = 'indoor' | 'outdoor' | 'none';\n\nexport type { BuildingFloorStackState };\n", "import { Floor, FloorStack } from '@mappedin/mappedin-js';\nimport { clampWithWarning } from '@packages/internal/common/math-utils';\nimport Logger from '@packages/internal/common/Mappedin.Logger';\n\n/**\n * Validates that a floor belongs to the specified floor stack.\n */\nexport function validateFloorForStack(floor: Floor, floorStack: FloorStack): boolean {\n\tif (!Floor.is(floor) || floor?.floorStack == null || !FloorStack.is(floorStack)) {\n\t\treturn false;\n\t}\n\n\tif (floor.floorStack.id !== floorStack.id) {\n\t\tLogger.warn(`Floor (${floor.id}) does not belong to floor stack (${floorStack.id}).`);\n\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n/**\n * Validates and clamps zoom threshold values.\n */\nexport function validateZoomThreshold(value: number, min: number, max: number, name: string): number {\n\treturn clampWithWarning(value, min, max, `${name} must be between ${min} and ${max}.`);\n}\n", "/* eslint-disable no-console*/\nexport const MI_DEBUG_KEY = 'mi-debug';\nexport const MI_ERROR_LABEL = '[MappedinJS]';\n\nexport enum E_SDK_LOG_LEVEL {\n\tLOG,\n\tWARN,\n\tERROR,\n\tSILENT,\n}\n\nexport function createLogger(name = '', { prefix = MI_ERROR_LABEL } = {}) {\n\tconst label = `${prefix}${name ? `-${name}` : ''}`;\n\n\tconst rnDebug = (type: 'log' | 'warn' | 'error', args: any[]) => {\n\t\tif (typeof window !== 'undefined' && (window as any).rnDebug) {\n\t\t\tconst processed = args.map(arg => {\n\t\t\t\tif (arg instanceof Error && arg.stack) {\n\t\t\t\t\treturn `${arg.message}\\n${arg.stack}`;\n\t\t\t\t}\n\n\t\t\t\treturn arg;\n\t\t\t});\n\t\t\t(window as any).rnDebug(`${name} ${type}: ${processed.join(' ')}`);\n\t\t}\n\t};\n\n\treturn {\n\t\tlogState: process.env.NODE_ENV === 'test' ? E_SDK_LOG_LEVEL.SILENT : E_SDK_LOG_LEVEL.LOG,\n\n\t\tlog(...args: any[]) {\n\t\t\tif (this.logState <= E_SDK_LOG_LEVEL.LOG) {\n\t\t\t\tconsole.log(label, ...args);\n\t\t\t\trnDebug('log', args);\n\t\t\t}\n\t\t},\n\n\t\twarn(...args: any[]) {\n\t\t\tif (this.logState <= E_SDK_LOG_LEVEL.WARN) {\n\t\t\t\tconsole.warn(label, ...args);\n\t\t\t\trnDebug('warn', args);\n\t\t\t}\n\t\t},\n\n\t\terror(...args: any[]) {\n\t\t\tif (this.logState <= E_SDK_LOG_LEVEL.ERROR) {\n\t\t\t\tconsole.error(label, ...args);\n\n\t\t\t\trnDebug('error', args);\n\t\t\t}\n\t\t},\n\n\t\t// It's a bit tricky to prepend [MappedinJs] to assert and time because of how the output is structured in the console, so it is left out for simplicity\n\t\tassert(...args: any[]) {\n\t\t\tconsole.assert(...args);\n\t\t},\n\n\t\ttime(label: string) {\n\t\t\tconsole.time(label);\n\t\t},\n\n\t\ttimeEnd(label: string) {\n\t\t\tconsole.timeEnd(label);\n\t\t},\n\t\tsetLevel(level: E_SDK_LOG_LEVEL) {\n\t\t\tif (E_SDK_LOG_LEVEL.LOG <= level && level <= E_SDK_LOG_LEVEL.SILENT) {\n\t\t\t\tthis.logState = level;\n\t\t\t}\n\t\t},\n\t};\n}\n\nconst Logger = createLogger();\nexport function setLoggerLevel(level: E_SDK_LOG_LEVEL) {\n\tif (E_SDK_LOG_LEVEL.LOG <= level && level <= E_SDK_LOG_LEVEL.SILENT) {\n\t\tLogger.logState = level;\n\t}\n}\n\nexport default Logger;\n", "import Logger from './Mappedin.Logger';\n\n/**\n * Clamp a number between lower and upper bounds with a warning\n */\nexport function clampWithWarning(x: number, lower: number, upper: number, warning: string) {\n\tif (x < lower || x > upper) {\n\t\tLogger.warn(warning);\n\t}\n\n\treturn Math.min(upper, Math.max(lower, x));\n}\n", "import { createLogger } from '../../packages/common/Mappedin.Logger';\n\nexport const Logger = createLogger('', { prefix: '[DynamicFocus]' });\n", "import type { FloorStack, MapView } from '@mappedin/mappedin-js';\nimport { Logger } from './logger';\nimport type { Building } from './building';\n\nexport class Outdoors {\n\t__type = 'outdoors';\n\t#floorStack: FloorStack;\n\t#mapView: MapView;\n\n\tconstructor(floorStack: FloorStack, mapView: MapView) {\n\t\tthis.#floorStack = floorStack;\n\t\tthis.#mapView = mapView;\n\t}\n\n\tget id() {\n\t\treturn this.#floorStack.id;\n\t}\n\n\tget floorStack() {\n\t\treturn this.#floorStack;\n\t}\n\n\tget floor() {\n\t\t// outdoors should only have 1 floor\n\t\treturn this.#floorStack.defaultFloor;\n\t}\n\n\tmatchesFloorStack(floorStack: FloorStack | string) {\n\t\treturn floorStack === this.#floorStack || floorStack === this.#floorStack.id;\n\t}\n\n\t#setVisible(visible: boolean) {\n\t\tfor (const floor of this.#floorStack.floors) {\n\t\t\tthis.#mapView.updateState(floor, {\n\t\t\t\tvisible,\n\t\t\t});\n\t\t}\n\t}\n\n\tshow() {\n\t\tthis.#setVisible(true);\n\t}\n\n\thide() {\n\t\tthis.#setVisible(false);\n\t}\n\n\tdestroy() {\n\t\tif (!this.matchesFloorStack(this.#mapView.currentFloorStack)) {\n\t\t\tthis.hide();\n\t\t}\n\t}\n}\n\nexport function getOutdoorFloorStack(floorStacks: FloorStack[], buildingsSet: Map<string, Building>): FloorStack {\n\tconst outdoorFloorStack = floorStacks.find(floorStack => floorStack.type?.toLowerCase() === 'outdoor');\n\n\tif (outdoorFloorStack) {\n\t\treturn outdoorFloorStack;\n\t}\n\n\t// If no outdoor type found, find the first floor stack that does not have a facade or is already in the buildings set\n\tconst likelyOutdoorFloorStack = floorStacks.find(\n\t\tfloorStack => floorStack.facade == null && !buildingsSet.has(floorStack.id),\n\t);\n\n\tif (likelyOutdoorFloorStack) {\n\t\treturn likelyOutdoorFloorStack;\n\t}\n\n\tLogger.warn('No good candidate for the outdoor floor stack was found. Using the first floor stack.');\n\n\treturn floorStacks[0];\n}\n", "import { getMultiFloorState } from '@mappedin/mappedin-js';\nimport type { RequiredDeep } from 'type-fest';\nimport type { DynamicFocusState } from './types';\n\nexport const DEFAULT_STATE: RequiredDeep<DynamicFocusState> = {\n\tindoorZoomThreshold: 18,\n\toutdoorZoomThreshold: 17,\n\tsetFloorOnFocus: true,\n\tautoFocus: false,\n\tindoorAnimationOptions: {\n\t\tduration: 150,\n\t},\n\toutdoorAnimationOptions: {\n\t\tduration: 150,\n\t},\n\tautoAdjustFacadeHeights: false,\n\tmode: 'default-floor',\n\tpreloadFloors: true,\n\tcustomMultiFloorVisibilityState: getMultiFloorState,\n\tdynamicBuildingInteriors: true,\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["Floor", "getMultiFloorState", "getMultiFloorState", "Floor", "FloorStack", "label", "Floor", "FloorStack", "Logger", "Logger", "Logger", "Floor", "getMultiFloorState"]
7
+ }
@@ -12847,24 +12847,24 @@ declare module '@mappedin/dynamic-focus/mappedin-js/src/api-geojson/directions/u
12847
12847
  * @param mapData - The map data instance
12848
12848
  * @returns The node ids
12849
12849
  */
12850
- export function nearestNodeIdsSync(feature: TNearestCandidate, mapData: MapDataInternal): string[];
12851
- export function nearestNodeIds(feature: TNearestCandidate, mapData: MapDataInternal): Promise<string[]>;
12850
+ export function nearestNodeIdsSync(feature: TNearestCandidate, mapData: MapDataInternal, enterpriseMode: boolean): string[];
12851
+ export function nearestNodeIds(feature: TNearestCandidate, mapData: MapDataInternal, enterpriseMode: boolean): Promise<string[]>;
12852
12852
  /** @deprecated use locationProfileNodeIds unless you must call this synchronously. */
12853
- export function locationProfileNodeIdsSync(target: LocationProfile, mapData: MapDataInternal): string[];
12854
- export function locationProfileNodeIds(target: LocationProfile, mapData: MapDataInternal): Promise<string[]>;
12853
+ export function locationProfileNodeIdsSync(target: LocationProfile, mapData: MapDataInternal, enterpriseMode: boolean): string[];
12854
+ export function locationProfileNodeIds(target: LocationProfile, mapData: MapDataInternal, enterpriseMode: boolean): Promise<string[]>;
12855
12855
  export function doorNodeIds(target: Door, mapData: MapDataInternal): string[];
12856
12856
  export function areaNodeIds(target: Area, mapData: MapDataInternal): string[];
12857
12857
  export function spaceNodeIds(target: Space, mapData: MapDataInternal): string[];
12858
12858
  /**
12859
12859
  * @deprecated use connectionNodeIds unless you must call this synchronously.
12860
12860
  */
12861
- export function connectionNodeIdsSync(target: Connection, mapData: MapDataInternal): string[];
12862
- export function connectionNodeIds(target: Connection, mapData: MapDataInternal): Promise<string[]>;
12861
+ export function connectionNodeIdsSync(target: Connection, mapData: MapDataInternal, enterpriseMode: boolean): string[];
12862
+ export function connectionNodeIds(target: Connection, mapData: MapDataInternal, enterpriseMode: boolean): Promise<string[]>;
12863
12863
  export function mapObjectNodeIds(target: MapObject, mapData: MapDataInternal): string[];
12864
12864
  export function facadeNodeIds(target: Facade, mapData: MapDataInternal): string[];
12865
12865
  export function enterpriseLocationNodeIds(target: EnterpriseLocation): string[];
12866
12866
  /** @deprecated use getNodesFromTarget unless you must call this synchronously. */
12867
- export function getNodesFromTargetSync(target: TNavigationTarget, mapData: MapDataInternal): string[];
12867
+ export function getNodesFromTargetSync(target: TNavigationTarget, mapData: MapDataInternal, enterpriseMode: boolean): string[];
12868
12868
  /**
12869
12869
  * Get the nodes from the navigation target.
12870
12870
  *
@@ -12872,7 +12872,7 @@ declare module '@mappedin/dynamic-focus/mappedin-js/src/api-geojson/directions/u
12872
12872
  * @param target
12873
12873
  * @param mapData
12874
12874
  */
12875
- export function getNodesFromTarget(target: TNavigationTarget, mapData: MapDataInternal): Promise<string[]>;
12875
+ export function getNodesFromTarget(target: TNavigationTarget, mapData: MapDataInternal, enterpriseMode: boolean): Promise<string[]>;
12876
12876
  export function getDepartureFromDirections(directions: DirectionsCollection, from: TNavigationTarget[], featureToNodeIdsMap: Map<TNavigationTarget, string[]>): TNavigationTarget;
12877
12877
  export function getDestinationFromDirections(directions: DirectionsCollection, to: TNavigationTarget[], featureToNodeIdsMap: Map<TNavigationTarget, string[]>): TNavigationTarget;
12878
12878
  export {};
package/lib/esm/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  DynamicFocus
3
- } from "./chunk-NUMVRZNR.js";
3
+ } from "./chunk-RSECYADN.js";
4
4
  export {
5
5
  DynamicFocus
6
6
  };
@@ -12857,24 +12857,24 @@ declare module '@mappedin/dynamic-focus/react/mappedin-js/src/api-geojson/direct
12857
12857
  * @param mapData - The map data instance
12858
12858
  * @returns The node ids
12859
12859
  */
12860
- export function nearestNodeIdsSync(feature: TNearestCandidate, mapData: MapDataInternal): string[];
12861
- export function nearestNodeIds(feature: TNearestCandidate, mapData: MapDataInternal): Promise<string[]>;
12860
+ export function nearestNodeIdsSync(feature: TNearestCandidate, mapData: MapDataInternal, enterpriseMode: boolean): string[];
12861
+ export function nearestNodeIds(feature: TNearestCandidate, mapData: MapDataInternal, enterpriseMode: boolean): Promise<string[]>;
12862
12862
  /** @deprecated use locationProfileNodeIds unless you must call this synchronously. */
12863
- export function locationProfileNodeIdsSync(target: LocationProfile, mapData: MapDataInternal): string[];
12864
- export function locationProfileNodeIds(target: LocationProfile, mapData: MapDataInternal): Promise<string[]>;
12863
+ export function locationProfileNodeIdsSync(target: LocationProfile, mapData: MapDataInternal, enterpriseMode: boolean): string[];
12864
+ export function locationProfileNodeIds(target: LocationProfile, mapData: MapDataInternal, enterpriseMode: boolean): Promise<string[]>;
12865
12865
  export function doorNodeIds(target: Door, mapData: MapDataInternal): string[];
12866
12866
  export function areaNodeIds(target: Area, mapData: MapDataInternal): string[];
12867
12867
  export function spaceNodeIds(target: Space, mapData: MapDataInternal): string[];
12868
12868
  /**
12869
12869
  * @deprecated use connectionNodeIds unless you must call this synchronously.
12870
12870
  */
12871
- export function connectionNodeIdsSync(target: Connection, mapData: MapDataInternal): string[];
12872
- export function connectionNodeIds(target: Connection, mapData: MapDataInternal): Promise<string[]>;
12871
+ export function connectionNodeIdsSync(target: Connection, mapData: MapDataInternal, enterpriseMode: boolean): string[];
12872
+ export function connectionNodeIds(target: Connection, mapData: MapDataInternal, enterpriseMode: boolean): Promise<string[]>;
12873
12873
  export function mapObjectNodeIds(target: MapObject, mapData: MapDataInternal): string[];
12874
12874
  export function facadeNodeIds(target: Facade, mapData: MapDataInternal): string[];
12875
12875
  export function enterpriseLocationNodeIds(target: EnterpriseLocation): string[];
12876
12876
  /** @deprecated use getNodesFromTarget unless you must call this synchronously. */
12877
- export function getNodesFromTargetSync(target: TNavigationTarget, mapData: MapDataInternal): string[];
12877
+ export function getNodesFromTargetSync(target: TNavigationTarget, mapData: MapDataInternal, enterpriseMode: boolean): string[];
12878
12878
  /**
12879
12879
  * Get the nodes from the navigation target.
12880
12880
  *
@@ -12882,7 +12882,7 @@ declare module '@mappedin/dynamic-focus/react/mappedin-js/src/api-geojson/direct
12882
12882
  * @param target
12883
12883
  * @param mapData
12884
12884
  */
12885
- export function getNodesFromTarget(target: TNavigationTarget, mapData: MapDataInternal): Promise<string[]>;
12885
+ export function getNodesFromTarget(target: TNavigationTarget, mapData: MapDataInternal, enterpriseMode: boolean): Promise<string[]>;
12886
12886
  export function getDepartureFromDirections(directions: DirectionsCollection, from: TNavigationTarget[], featureToNodeIdsMap: Map<TNavigationTarget, string[]>): TNavigationTarget;
12887
12887
  export function getDestinationFromDirections(directions: DirectionsCollection, to: TNavigationTarget[], featureToNodeIdsMap: Map<TNavigationTarget, string[]>): TNavigationTarget;
12888
12888
  export {};
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DynamicFocus,
3
3
  __name
4
- } from "../chunk-NUMVRZNR.js";
4
+ } from "../chunk-RSECYADN.js";
5
5
 
6
6
  // src/react/use-dynamic-focus.ts
7
7
  import { useCallback, useState, useMemo } from "react";
@@ -100,8 +100,8 @@ var EXTENSION_SOURCE_PLACEHOLDER = `
100
100
  throw new Error('Module not found: ' + id);
101
101
  });
102
102
 
103
- "use strict";var DynamicFocus=(()=>{var J=Object.defineProperty;var Ut=Object.getOwnPropertyDescriptor;var \$t=Object.getOwnPropertyNames;var Ht=Object.prototype.hasOwnProperty;var Mt=r=>{throw TypeError(r)};var qt=(r,t,e)=>t in r?J(r,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):r[t]=e;var n=(r,t)=>J(r,"name",{value:t,configurable:!0}),nt=(r=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(r,{get:(t,e)=>(typeof require<"u"?require:t)[e]}):r)(function(r){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+r+'" is not supported')});var Wt=(r,t)=>{for(var e in t)J(r,e,{get:t[e],enumerable:!0})},Kt=(r,t,e,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of \$t(t))!Ht.call(r,i)&&i!==e&&J(r,i,{get:()=>t[i],enumerable:!(a=Ut(t,i))||a.enumerable});return r};var zt=r=>Kt(J({},"__esModule",{value:!0}),r);var m=(r,t,e)=>qt(r,typeof t!="symbol"?t+"":t,e),pt=(r,t,e)=>t.has(r)||Mt("Cannot "+e);var o=(r,t,e)=>(pt(r,t,"read from private field"),e?e.call(r):t.get(r)),u=(r,t,e)=>t.has(r)?Mt("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(r):t.set(r,e),l=(r,t,e,a)=>(pt(r,t,"write to private field"),a?a.call(r,e):t.set(r,e),e),b=(r,t,e)=>(pt(r,t,"access private method"),e);var oo={};Wt(oo,{DynamicFocus:()=>ft});var mt=nt("@mappedin/mappedin-js");function Vt(r,t){if(r==null||t==null)return r===t;if(r.length!==t.length)return!1;for(let e=0;e<r.length;e++)if(r[e]!==t[e])return!1;return!0}n(Vt,"arraysEqual");var Ft=class Ft{constructor(){m(this,"_subscribers",{});m(this,"_destroyed",!1)}publish(t,e){!this._subscribers||!this._subscribers[t]||this._destroyed||this._subscribers[t].forEach(function(a){typeof a=="function"&&a(e)})}on(t,e){(!this._subscribers||this._destroyed)&&(this._subscribers={}),this._subscribers[t]=this._subscribers[t]||[],this._subscribers[t].push(e)}off(t,e){if(!this._subscribers||this._subscribers[t]==null||this._destroyed)return;let a=this._subscribers[t].indexOf(e);a!==-1&&this._subscribers[t].splice(a,1)}destroy(){this._destroyed=!0,this._subscribers={}}};n(Ft,"PubSub");var lt=Ft;var Y=nt("@mappedin/mappedin-js");var E,X,w,S,F,k,j,G,gt=class gt{constructor(t,e){m(this,"__type","building");u(this,E);u(this,X,new Map);u(this,w,new Map);u(this,S,[]);u(this,F);u(this,k);m(this,"defaultFloor");m(this,"activeFloor");m(this,"excluded",!1);m(this,"floorsAltitudesMap",new Map);m(this,"aboveGroundFloors",[]);u(this,j);u(this,G);l(this,E,t),l(this,X,new Map(t.floors.map(i=>[i.id,i]))),l(this,w,new Map(t.floors.map(i=>[i.elevation,i]))),l(this,S,Array.from(o(this,w).values()).sort((i,c)=>i.elevation-c.elevation)),this.defaultFloor=t.defaultFloor,this.activeFloor=this.defaultFloor,l(this,F,e),this.aboveGroundFloors=o(this,S).filter(i=>i.elevation>=0);let a=t.facade?.spaces.map(i=>o(this,F).getState(i)).sort((i,c)=>i.altitude-c.altitude);if(a&&a.length===this.aboveGroundFloors.length)for(let i in this.aboveGroundFloors){let c=this.aboveGroundFloors[i],y=a[i];this.floorsAltitudesMap.set(c.elevation,{altitude:y.altitude,effectiveHeight:y.height})}}get id(){return o(this,E).id}get name(){return o(this,E).name}get floors(){return o(this,E).floors}get floorStack(){return o(this,E)}get facade(){return o(this,E).facade}get isCurrentFloorStack(){return this.id===o(this,F).currentFloorStack.id}get isIndoor(){let t=o(this,F).getState(this.facade);return this.isCurrentFloorStack||t?.visible===!1&&t?.opacity===0}get canSetFloor(){return this.isIndoor||!this.excluded}get maxElevation(){return o(this,j)==null&&l(this,j,Math.max(...o(this,w).keys())),o(this,j)}get minElevation(){return o(this,G)==null&&l(this,G,Math.min(...o(this,w).keys())),o(this,G)}has(t){return Y.Floor.is(t)?o(this,X).has(t.id):Y.FloorStack.is(t)?t.id===o(this,E).id:Y.Facade.is(t)?t.id===this.facade.id:!1}getFloorByElevation(t){return o(this,w).get(t)}getNearestFloorByElevation(t){let e=this.getFloorByElevation(t);if(e)return e;if(t>=0){if(t>this.maxElevation)return o(this,S)[o(this,S).length-1];for(let a=o(this,S).length-1;a>=0;a--){let i=o(this,S)[a];if(i.elevation<=t)return i}}else{if(t<this.minElevation)return o(this,S)[0];for(let a of o(this,S))if(a.elevation>=t)return a}}getHighestFloor(){return o(this,S)[o(this,S).length-1]}cancelAnimation(){o(this,k)&&(o(this,k).animation.cancel(),l(this,k,void 0))}async animateFacade(t,e={duration:150}){let a=o(this,k)?.state||o(this,F).getState(this.facade);if(!a||!t||a?.opacity===t.opacity&&a?.visible===t.visible)return{result:"completed"};this.cancelAnimation();let{opacity:i,visible:c}=t;if(o(this,F).updateState(this.facade,{visible:!0}),i!==void 0){l(this,k,{animation:o(this,F).animateState(this.facade,{opacity:i},{duration:e.duration}),state:t});let y=await o(this,k).animation;if(l(this,k,void 0),y.result==="cancelled")return y}return c===!1&&o(this,F).updateState(this.facade,{visible:c}),{result:"completed"}}destroy(){this.cancelAnimation(),o(this,E).floors.forEach(t=>{o(this,F).updateState(t,{visible:t.id===o(this,F).currentFloor.id})}),this.has(o(this,F).currentFloor)||o(this,F).updateState(this.facade,{visible:!0,opacity:1})}};E=new WeakMap,X=new WeakMap,w=new WeakMap,S=new WeakMap,F=new WeakMap,k=new WeakMap,j=new WeakMap,G=new WeakMap,n(gt,"Building");var ut=gt;function xt(r,t,e){return r>=t?"in-range":r<=e?"out-of-range":"transition"}n(xt,"getZoomState");function dt(r,t,e){if(r.__type==="outdoors"&&"floor"in r)return r.floor;let a=r;if(a.excluded)return a.activeFloor;switch(t){case"lock-elevation":return a.getFloorByElevation(e);case"nearest-elevation":return a.getNearestFloorByElevation(e);default:break}return a.isIndoor?a.activeFloor:a.defaultFloor}n(dt,"getFloorToShow");function Qt(r,t){return{facade:r,state:{type:"facade",visible:!t,opacity:t?0:1}}}n(Qt,"getFacadeState");function Jt(r,t,e){return{outdoorOpacity:1,floorStates:r.floors.map(a=>{let i=a.id===t.id&&e;return{floor:a,state:{type:"floor",visible:i,geometry:{visible:i},labels:{enabled:i},markers:{enabled:i},footprint:{visible:!1},occlusion:{enabled:!1}}}})}}n(Jt,"getSingleBuildingState");function Ot(r,t){if(!t.includes("lock-elevation"))return 1;for(let e of r)if(e.outdoorOpacity>=0&&e.outdoorOpacity<=1)return e.outdoorOpacity;return 1}n(Ot,"getOutdoorOpacity");function Bt(r,t,e){switch(e){case"in-range":return r[0]?.canSetFloor?r[0]:void 0;case"out-of-range":return t;case"transition":default:return}}n(Bt,"getSetFloorTargetFromZoomState");function _t(r,t,e,a,i,c,y,p,z,rt,O){let Z=new Map;for(let f of r){let P=t.has(f.id),R=yt(f,e,a==="in-range",P,i,c,p.includes(f.id),O),Q=e.floorStack.id===f.id?f.activeFloor:dt(f,i,c),st=z.enabled?rt(f.floors,Q||f.activeFloor,z?.floorGap,y,f.floorsAltitudesMap):Jt(f.floorStack,Q||f.activeFloor,R),Yt=Qt(f.facade,R);Z.set(f.id,{building:f,showIndoor:R,floorStackState:st,facadeState:Yt,inFocus:P,floorToShow:Q})}return Z}n(_t,"getBuildingStates");function Nt(r,t){return r.excluded?"none":t?"indoor":"outdoor"}n(Nt,"getBuildingAnimationType");function yt(r,t,e,a,i,c,y,p){if(r.id===t.floorStack.id)return!0;if(r.excluded)return!1;if(y===!0)return!0;if(!p)return t.floorStack.type!=="Outdoor";if(!e||!a)return!1;switch(i){case"lock-elevation":return r.getFloorByElevation(c)!=null;default:break}return!0}n(yt,"shouldShowIndoor");function It(r,t,e){return r!==t&&!e}n(It,"shouldDeferSetFloor");var Lt=["default-floor","lock-elevation","nearest-elevation"];var ct=nt("@mappedin/mappedin-js");var Xt="[MappedinJS]";function St(r="",{prefix:t=Xt}={}){let e=\`\${t}\${r?\`-\${r}\`:""}\`,a=n((i,c)=>{if(typeof window<"u"&&window.rnDebug){let y=c.map(p=>p instanceof Error&&p.stack?\`\${p.message}
104
- \${p.stack}\`:p);window.rnDebug(\`\${r} \${i}: \${y.join(" ")}\`)}},"rnDebug");return{logState:0,log(...i){this.logState<=0&&(console.log(e,...i),a("log",i))},warn(...i){this.logState<=1&&(console.warn(e,...i),a("warn",i))},error(...i){this.logState<=2&&(console.error(e,...i),a("error",i))},assert(...i){console.assert(...i)},time(i){console.time(i)},timeEnd(i){console.timeEnd(i)},setLevel(i){0<=i&&i<=3&&(this.logState=i)}}}n(St,"createLogger");var to=St();var U=to;function Ct(r,t,e,a){return(r<t||r>e)&&U.warn(a),Math.min(e,Math.max(t,r))}n(Ct,"clampWithWarning");function bt(r,t){return!ct.Floor.is(r)||r?.floorStack==null||!ct.FloorStack.is(t)?!1:r.floorStack.id!==t.id?(U.warn(\`Floor (\${r.id}) does not belong to floor stack (\${t.id}).\`),!1):!0}n(bt,"validateFloorForStack");function Et(r,t,e,a){return Ct(r,t,e,\`\${a} must be between \${t} and \${e}.\`)}n(Et,"validateZoomThreshold");var \$=St("",{prefix:"[DynamicFocus]"});var D,H,tt,vt,kt=class kt{constructor(t,e){u(this,tt);m(this,"__type","outdoors");u(this,D);u(this,H);l(this,D,t),l(this,H,e)}get id(){return o(this,D).id}get floorStack(){return o(this,D)}get floor(){return o(this,D).defaultFloor}matchesFloorStack(t){return t===o(this,D)||t===o(this,D).id}show(){b(this,tt,vt).call(this,!0)}hide(){b(this,tt,vt).call(this,!1)}destroy(){this.matchesFloorStack(o(this,H).currentFloorStack)||this.hide()}};D=new WeakMap,H=new WeakMap,tt=new WeakSet,vt=n(function(t){for(let e of o(this,D).floors)o(this,H).updateState(e,{visible:t})},"#setVisible"),n(kt,"Outdoors");var ht=kt;function Zt(r,t){let e=r.find(i=>i.type?.toLowerCase()==="outdoor");if(e)return e;let a=r.find(i=>i.facade==null&&!t.has(i.id));return a||(\$.warn("No good candidate for the outdoor floor stack was found. Using the first floor stack."),r[0])}n(Zt,"getOutdoorFloorStack");var Pt=nt("@mappedin/mappedin-js"),Rt={indoorZoomThreshold:18,outdoorZoomThreshold:17,setFloorOnFocus:!0,autoFocus:!1,indoorAnimationOptions:{duration:150},outdoorAnimationOptions:{duration:150},autoAdjustFacadeHeights:!1,mode:"default-floor",preloadFloors:!0,customMultiFloorVisibilityState:Pt.getMultiFloorState,dynamicBuildingInteriors:!0};var v,s,B,d,_,N,h,M,I,L,A,q,T,V,W,x,g,Dt,Tt,ot,et,it,at,K,At,jt,Gt,C,wt=class wt{constructor(t){u(this,g);u(this,v);u(this,s);u(this,B);u(this,d,Rt);u(this,_,[]);u(this,N,new Set);u(this,h,new Map);u(this,M);u(this,I,!1);u(this,L,!1);u(this,A,0);u(this,q,0);u(this,T,"transition");u(this,V,"outdoor");u(this,W,[]);u(this,x,!1);m(this,"sceneUpdateQueue",Promise.resolve());m(this,"on",n((t,e)=>{o(this,v).on(t,e)},"on"));m(this,"off",n((t,e)=>{o(this,v).off(t,e)},"off"));u(this,ot,n(t=>{if(!this.isEnabled)return;let{facades:e}=t;if(!(Vt(e,this.focusedFacades)&&o(this,V)==="transition"&&!o(this,L))){if(l(this,L,!1),l(this,_,[]),o(this,N).clear(),e.length>0)for(let a of e){let i=o(this,h).get(a.floorStack.id);i&&(o(this,N).add(i.id),o(this,_).push(i))}o(this,d).autoFocus&&this.focus()}},"#handleFacadesInViewChange"));u(this,et,n(async t=>{if(!this.isEnabled)return;let{floor:e}=t,a=o(this,h).get(e.floorStack.id);if(a&&(a.activeFloor=e),a?.excluded===!1&&!o(this,M).matchesFloorStack(e.floorStack)&&l(this,A,e.elevation),o(this,s).manualFloorVisibility===!0){t.reason!=="dynamic-focus"&&(await o(this,C).call(this,e),o(this,v).publish("focus",{facades:this.focusedFacades}));let i=a?.floorsAltitudesMap.get(e.elevation)?.altitude??0;o(this,s).options.multiFloorView!=null&&o(this,s).options.multiFloorView?.enabled&&o(this,s).options.multiFloorView?.updateCameraElevationOnFloorChange&&o(this,s).Camera.elevation!==i&&o(this,s).Camera.animateElevation(i,{duration:750,easing:"ease-in-out"})}},"#handleFloorChangeStart"));u(this,it,n(()=>{l(this,I,!0)},"#handleUserInteractionStart"));u(this,at,n(()=>{l(this,I,!1)},"#handleUserInteractionEnd"));u(this,K,n(t=>{if(!this.isEnabled)return;let{zoomLevel:e}=t,a=xt(e,o(this,d).indoorZoomThreshold,o(this,d).outdoorZoomThreshold);o(this,T)!==a&&(l(this,T,a),a==="in-range"?this.setIndoor():a==="out-of-range"&&this.setOutdoor())},"#handleCameraChange"));u(this,C,n(async t=>{if(o(this,s).manualFloorVisibility!==!0||!this.isEnabled)return;let e=t||o(this,s).currentFloor,a=o(this,s).options.multiFloorView,i=o(this,s).Navigation?.floors?.map(p=>p.id)||[],c=o(this,s).Navigation?.floorStacks.map(p=>p.id)||[],y=new Promise(async p=>{await this.sceneUpdateQueue;let z=_t(Array.from(o(this,h).values()),o(this,N),e,o(this,T),o(this,d).mode,o(this,A),i,c,a,o(this,d).customMultiFloorVisibilityState??mt.getMultiFloorState,o(this,d).dynamicBuildingInteriors),rt=[];await Promise.all(Array.from(z.values()).map(async O=>{let{building:Z,showIndoor:f,floorStackState:P,facadeState:R,inFocus:Q}=O;rt.push(P);let st=Nt(Z,f);if(st==="indoor")return b(this,g,jt).call(this,Z,P,R,Q);if(st==="outdoor")return b(this,g,Gt).call(this,Z,P,R,c)})),o(this,s).Outdoor.setOpacity(Ot(rt,o(this,d).mode)),l(this,W,o(this,_).filter(O=>z.get(O.id)?.showIndoor===!0).map(O=>O.facade)),o(this,v).publish("focus",{facades:o(this,W)}),p()});return this.sceneUpdateQueue=y,y},"#applyBuildingStates"));l(this,v,new lt),l(this,s,t),\$.setLevel(U.logState),l(this,B,o(this,s).getMapData()),l(this,A,o(this,s).currentFloor.elevation),l(this,q,o(this,s).Camera.elevation);for(let e of o(this,B).getByType("facade"))o(this,h).set(e.floorStack.id,new ut(e.floorStack,o(this,s)));l(this,M,new ht(Zt(o(this,B).getByType("floor-stack"),o(this,h)),o(this,s))),o(this,s).on("floor-change-start",o(this,et)),o(this,s).on("camera-change",o(this,K)),o(this,s).on("facades-in-view-change",o(this,ot)),o(this,s).on("user-interaction-start",o(this,it)),o(this,s).on("user-interaction-end",o(this,at))}enable(t){if(o(this,x)){\$.warn("enable() called on an already enabled Dynamic Focus instance.");return}l(this,x,!0),o(this,s).manualFloorVisibility=!0,o(this,M).show(),this.updateState({...o(this,d),...t}),o(this,K).call(this,{zoomLevel:o(this,s).Camera.zoomLevel,center:o(this,s).Camera.center,bearing:o(this,s).Camera.bearing,pitch:o(this,s).Camera.pitch}),o(this,s).Camera.updateFacadesInView()}disable(){if(!o(this,x)){\$.warn("disable() called on an already disabled Dynamic Focus instance.");return}l(this,x,!1),o(this,s).manualFloorVisibility=!1}get isEnabled(){return o(this,x)}get isIndoor(){return o(this,V)==="indoor"}get isOutdoor(){return o(this,V)==="outdoor"}setIndoor(){l(this,V,"indoor"),l(this,T,"in-range"),b(this,g,Dt).call(this)}setOutdoor(){l(this,V,"outdoor"),l(this,T,"out-of-range"),b(this,g,Dt).call(this)}get focusedFacades(){return[...o(this,W)]}getState(){return{...o(this,d)}}updateState(t){let e=!1;t.indoorZoomThreshold!=null&&(t.indoorZoomThreshold=Et(t.indoorZoomThreshold,o(this,d).outdoorZoomThreshold,o(this,s).Camera.maxZoomLevel,"indoorZoomThreshold")),t.outdoorZoomThreshold!=null&&(t.outdoorZoomThreshold=Et(t.outdoorZoomThreshold,o(this,s).Camera.minZoomLevel,o(this,d).indoorZoomThreshold,"outdoorZoomThreshold")),t.mode!=null&&(t.mode=Lt.includes(t.mode)?t.mode:"default-floor"),t.autoAdjustFacadeHeights!=null&&(o(this,d).autoAdjustFacadeHeights=t.autoAdjustFacadeHeights),t.dynamicBuildingInteriors!=null&&t.dynamicBuildingInteriors!==o(this,d).dynamicBuildingInteriors&&(e=!0),l(this,d,Object.assign({},o(this,d),Object.fromEntries(Object.entries(t).filter(([,a])=>a!=null)))),t.mode!=null&&t.preloadFloors&&b(this,g,Tt).call(this,t.mode),e&&o(this,C).call(this)}destroy(){this.disable(),o(this,s).off("facades-in-view-change",o(this,ot)),o(this,s).off("floor-change-start",o(this,et)),o(this,s).off("camera-change",o(this,K)),o(this,s).off("user-interaction-start",o(this,it)),o(this,s).off("user-interaction-end",o(this,at)),o(this,h).forEach(t=>t.destroy()),o(this,M).destroy(),o(this,v).destroy()}async focus(t=o(this,d).setFloorOnFocus){if(t)if(It(o(this,q),o(this,s).Camera.elevation,o(this,I)))l(this,q,o(this,s).Camera.elevation),l(this,L,!0);else{let e=Bt(o(this,_),o(this,M),o(this,T)),a=e?dt(e,o(this,d).mode,o(this,A)):void 0;a&&a.id!==o(this,s).currentFloor.id&&o(this,s).setFloor(a,{context:"dynamic-focus"})}await o(this,C).call(this),o(this,v).publish("focus",{facades:this.focusedFacades})}preloadFloors(){b(this,g,Tt).call(this,o(this,d).mode)}setDefaultFloorForStack(t,e){if(!bt(e,t))return;let a=o(this,h).get(t.id);a&&(a.defaultFloor=e)}resetDefaultFloorForStack(t){let e=o(this,h).get(t.id);e&&(e.defaultFloor=t.defaultFloor)}getDefaultFloorForStack(t){return o(this,h).get(t.id)?.defaultFloor||t.defaultFloor||t.floors[0]}setCurrentFloorForStack(t,e){if(!bt(e,t))return;let a=o(this,h).get(t.id);a&&(a.activeFloor=e,o(this,C).call(this))}exclude(t){let e=Array.isArray(t)?t:[t];for(let a of e){let i=o(this,h).get(a.id);i&&(i.excluded=!0)}}include(t){let e=Array.isArray(t)?t:[t];for(let a of e){let i=o(this,h).get(a.id);i&&(i.excluded=!1)}}getCurrentFloorForStack(t){return o(this,h).get(t.id)?.activeFloor||this.getDefaultFloorForStack(t)}};v=new WeakMap,s=new WeakMap,B=new WeakMap,d=new WeakMap,_=new WeakMap,N=new WeakMap,h=new WeakMap,M=new WeakMap,I=new WeakMap,L=new WeakMap,A=new WeakMap,q=new WeakMap,T=new WeakMap,V=new WeakMap,W=new WeakMap,x=new WeakMap,g=new WeakSet,Dt=n(function(){o(this,d).autoFocus&&(o(this,I)?this.focus():l(this,L,!0)),o(this,v).publish("state-change")},"#handleViewStateChange"),Tt=n(function(t){o(this,s).preloadFloors(o(this,B).getByType("facade").map(e=>dt(o(this,h).get(e.floorStack.id),t,o(this,A))).filter(e=>e!=null&&mt.Floor.is(e)))},"#preloadFloors"),ot=new WeakMap,et=new WeakMap,it=new WeakMap,at=new WeakMap,K=new WeakMap,At=n(function(t,e,a){t.forEach(i=>{if(i.floor)if(e){let c=a!==void 0?{...i.state,labels:{...i.state.labels,enabled:i.state.labels.enabled&&a},markers:{...i.state.markers,enabled:i.state.markers.enabled&&a},occlusion:{...i.state.occlusion,enabled:i.state.occlusion.enabled&&a}}:i.state;o(this,s).updateState(i.floor,c)}else o(this,s).updateState(i.floor,{visible:!1})})},"#updateFloorVisibility"),jt=n(async function(t,e,a,i){return b(this,g,At).call(this,e.floorStates,!0,i),t.animateFacade(a.state,o(this,d).indoorAnimationOptions)},"#animateIndoorSequence"),Gt=n(async function(t,e,a,i){let c=await t.animateFacade(a.state,o(this,d).outdoorAnimationOptions);return c.result==="completed"&&b(this,g,At).call(this,e.floorStates,yt(t,o(this,s).currentFloor,o(this,T)==="in-range",o(this,N).has(t.id),o(this,d).mode,o(this,A),i.includes(t.floorStack.id),o(this,d).dynamicBuildingInteriors)),c},"#animateOutdoorSequence"),C=new WeakMap,n(wt,"DynamicFocus");var ft=wt;return zt(oo);})();
103
+ "use strict";var DynamicFocus=(()=>{var J=Object.defineProperty;var Ut=Object.getOwnPropertyDescriptor;var \$t=Object.getOwnPropertyNames;var Ht=Object.prototype.hasOwnProperty;var Mt=r=>{throw TypeError(r)};var qt=(r,t,e)=>t in r?J(r,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):r[t]=e;var s=(r,t)=>J(r,"name",{value:t,configurable:!0}),st=(r=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(r,{get:(t,e)=>(typeof require<"u"?require:t)[e]}):r)(function(r){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+r+'" is not supported')});var Wt=(r,t)=>{for(var e in t)J(r,e,{get:t[e],enumerable:!0})},Kt=(r,t,e,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of \$t(t))!Ht.call(r,i)&&i!==e&&J(r,i,{get:()=>t[i],enumerable:!(a=Ut(t,i))||a.enumerable});return r};var zt=r=>Kt(J({},"__esModule",{value:!0}),r);var m=(r,t,e)=>qt(r,typeof t!="symbol"?t+"":t,e),pt=(r,t,e)=>t.has(r)||Mt("Cannot "+e);var o=(r,t,e)=>(pt(r,t,"read from private field"),e?e.call(r):t.get(r)),u=(r,t,e)=>t.has(r)?Mt("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(r):t.set(r,e),l=(r,t,e,a)=>(pt(r,t,"write to private field"),a?a.call(r,e):t.set(r,e),e),b=(r,t,e)=>(pt(r,t,"access private method"),e);var oo={};Wt(oo,{DynamicFocus:()=>ft});var mt=st("@mappedin/mappedin-js");function Vt(r,t){if(r==null||t==null)return r===t;if(r.length!==t.length)return!1;for(let e=0;e<r.length;e++)if(r[e]!==t[e])return!1;return!0}s(Vt,"arraysEqual");var Ft=class Ft{constructor(){m(this,"_subscribers",{});m(this,"_destroyed",!1)}publish(t,e){!this._subscribers||!this._subscribers[t]||this._destroyed||this._subscribers[t].forEach(function(a){typeof a=="function"&&a(e)})}on(t,e){(!this._subscribers||this._destroyed)&&(this._subscribers={}),this._subscribers[t]=this._subscribers[t]||[],this._subscribers[t].push(e)}off(t,e){if(!this._subscribers||this._subscribers[t]==null||this._destroyed)return;let a=this._subscribers[t].indexOf(e);a!==-1&&this._subscribers[t].splice(a,1)}destroy(){this._destroyed=!0,this._subscribers={}}};s(Ft,"PubSub");var lt=Ft;var Y=st("@mappedin/mappedin-js");var E,X,w,S,F,k,j,G,gt=class gt{constructor(t,e){m(this,"__type","building");u(this,E);u(this,X,new Map);u(this,w,new Map);u(this,S,[]);u(this,F);u(this,k);m(this,"defaultFloor");m(this,"activeFloor");m(this,"excluded",!1);m(this,"floorsAltitudesMap",new Map);m(this,"aboveGroundFloors",[]);u(this,j);u(this,G);l(this,E,t),l(this,X,new Map(t.floors.map(i=>[i.id,i]))),l(this,w,new Map(t.floors.map(i=>[i.elevation,i]))),l(this,S,Array.from(o(this,w).values()).sort((i,c)=>i.elevation-c.elevation)),this.defaultFloor=t.defaultFloor,this.activeFloor=this.defaultFloor,l(this,F,e),this.aboveGroundFloors=o(this,S).filter(i=>i.elevation>=0);let a=t.facade?.spaces.map(i=>o(this,F).getState(i)).sort((i,c)=>i.altitude-c.altitude);if(a&&a.length===this.aboveGroundFloors.length)for(let i in this.aboveGroundFloors){let c=this.aboveGroundFloors[i],y=a[i];this.floorsAltitudesMap.set(c.elevation,{altitude:y.altitude,effectiveHeight:y.height})}}get id(){return o(this,E).id}get name(){return o(this,E).name}get floors(){return o(this,E).floors}get floorStack(){return o(this,E)}get facade(){return o(this,E).facade}get isCurrentFloorStack(){return this.id===o(this,F).currentFloorStack.id}get isIndoor(){let t=o(this,F).getState(this.facade);return this.isCurrentFloorStack||t?.visible===!1&&t?.opacity===0}get canSetFloor(){return this.isIndoor||!this.excluded}get maxElevation(){return o(this,j)==null&&l(this,j,Math.max(...o(this,w).keys())),o(this,j)}get minElevation(){return o(this,G)==null&&l(this,G,Math.min(...o(this,w).keys())),o(this,G)}has(t){return Y.Floor.is(t)?o(this,X).has(t.id):Y.FloorStack.is(t)?t.id===o(this,E).id:Y.Facade.is(t)?t.id===this.facade.id:!1}getFloorByElevation(t){return o(this,w).get(t)}getNearestFloorByElevation(t){let e=this.getFloorByElevation(t);if(e)return e;if(t>=0){if(t>this.maxElevation)return o(this,S)[o(this,S).length-1];for(let a=o(this,S).length-1;a>=0;a--){let i=o(this,S)[a];if(i.elevation<=t)return i}}else{if(t<this.minElevation)return o(this,S)[0];for(let a of o(this,S))if(a.elevation>=t)return a}}getHighestFloor(){return o(this,S)[o(this,S).length-1]}cancelAnimation(){o(this,k)&&(o(this,k).animation.cancel(),l(this,k,void 0))}async animateFacade(t,e={duration:150}){let a=o(this,k)?.state||o(this,F).getState(this.facade);if(!a||!t||a?.opacity===t.opacity&&a?.visible===t.visible)return{result:"completed"};this.cancelAnimation();let{opacity:i,visible:c}=t;if(o(this,F).updateState(this.facade,{visible:!0}),i!==void 0){l(this,k,{animation:o(this,F).animateState(this.facade,{opacity:i},{duration:e.duration}),state:t});let y=await o(this,k).animation;if(l(this,k,void 0),y.result==="cancelled")return y}return c===!1&&o(this,F).updateState(this.facade,{visible:c}),{result:"completed"}}destroy(){this.cancelAnimation(),o(this,E).floors.forEach(t=>{o(this,F).updateState(t,{visible:t.id===o(this,F).currentFloor.id})}),this.has(o(this,F).currentFloor)||o(this,F).updateState(this.facade,{visible:!0,opacity:1})}};E=new WeakMap,X=new WeakMap,w=new WeakMap,S=new WeakMap,F=new WeakMap,k=new WeakMap,j=new WeakMap,G=new WeakMap,s(gt,"Building");var ut=gt;function xt(r,t,e){return r>=t?"in-range":r<=e?"out-of-range":"transition"}s(xt,"getZoomState");function dt(r,t,e){if(r.__type==="outdoors"&&"floor"in r)return r.floor;let a=r;if(a.excluded)return a.activeFloor;switch(t){case"lock-elevation":return a.getFloorByElevation(e);case"nearest-elevation":return a.getNearestFloorByElevation(e);default:break}return a.isIndoor?a.activeFloor:a.defaultFloor}s(dt,"getFloorToShow");function Qt(r,t){return{facade:r,state:{type:"facade",visible:!t,opacity:t?0:1}}}s(Qt,"getFacadeState");function Jt(r,t,e){return{outdoorOpacity:1,floorStates:r.floors.map(a=>{let i=a.id===t.id&&e;return{floor:a,state:{type:"floor",visible:i,geometry:{visible:i},labels:{enabled:i},markers:{enabled:i},footprint:{visible:!1},occlusion:{enabled:!1}}}})}}s(Jt,"getSingleBuildingState");function Ot(r,t){if(!t.includes("lock-elevation"))return 1;for(let e of r)if(e.outdoorOpacity>=0&&e.outdoorOpacity<=1)return e.outdoorOpacity;return 1}s(Ot,"getOutdoorOpacity");function Bt(r,t,e){switch(e){case"in-range":return r[0]?.canSetFloor?r[0]:void 0;case"out-of-range":return t;case"transition":default:return}}s(Bt,"getSetFloorTargetFromZoomState");function _t(r,t,e,a,i,c,y,p,z,rt,O){let C=new Map;for(let f of r){let P=t.has(f.id),R=yt(f,e,a==="in-range",P,i,c,p.includes(f.id),O),Q=e.floorStack.id===f.id?f.activeFloor:dt(f,i,c),nt=z.enabled?rt(f.floors,Q||f.activeFloor,z?.floorGap,y,f.floorsAltitudesMap):Jt(f.floorStack,Q||f.activeFloor,R),Yt=Qt(f.facade,R);C.set(f.id,{building:f,showIndoor:R,floorStackState:nt,facadeState:Yt,inFocus:P,floorToShow:Q})}return C}s(_t,"getBuildingStates");function Nt(r,t){return r.excluded?"none":t?"indoor":"outdoor"}s(Nt,"getBuildingAnimationType");function yt(r,t,e,a,i,c,y,p){if(r.id===t.floorStack.id)return!0;if(r.excluded)return!1;if(y===!0)return!0;if(!p)return t.floorStack.type!=="Outdoor";if(!e||!a)return!1;switch(i){case"lock-elevation":return r.getFloorByElevation(c)!=null;default:break}return!0}s(yt,"shouldShowIndoor");function It(r,t,e){return r!==t&&!e}s(It,"shouldDeferSetFloor");var Lt=["default-floor","lock-elevation","nearest-elevation"];var ct=st("@mappedin/mappedin-js");var Xt="[MappedinJS]";function St(r="",{prefix:t=Xt}={}){let e=\`\${t}\${r?\`-\${r}\`:""}\`,a=s((i,c)=>{if(typeof window<"u"&&window.rnDebug){let y=c.map(p=>p instanceof Error&&p.stack?\`\${p.message}
104
+ \${p.stack}\`:p);window.rnDebug(\`\${r} \${i}: \${y.join(" ")}\`)}},"rnDebug");return{logState:0,log(...i){this.logState<=0&&(console.log(e,...i),a("log",i))},warn(...i){this.logState<=1&&(console.warn(e,...i),a("warn",i))},error(...i){this.logState<=2&&(console.error(e,...i),a("error",i))},assert(...i){console.assert(...i)},time(i){console.time(i)},timeEnd(i){console.timeEnd(i)},setLevel(i){0<=i&&i<=3&&(this.logState=i)}}}s(St,"createLogger");var to=St();var U=to;function Zt(r,t,e,a){return(r<t||r>e)&&U.warn(a),Math.min(e,Math.max(t,r))}s(Zt,"clampWithWarning");function bt(r,t){return!ct.Floor.is(r)||r?.floorStack==null||!ct.FloorStack.is(t)?!1:r.floorStack.id!==t.id?(U.warn(\`Floor (\${r.id}) does not belong to floor stack (\${t.id}).\`),!1):!0}s(bt,"validateFloorForStack");function Et(r,t,e,a){return Zt(r,t,e,\`\${a} must be between \${t} and \${e}.\`)}s(Et,"validateZoomThreshold");var \$=St("",{prefix:"[DynamicFocus]"});var D,H,tt,vt,kt=class kt{constructor(t,e){u(this,tt);m(this,"__type","outdoors");u(this,D);u(this,H);l(this,D,t),l(this,H,e)}get id(){return o(this,D).id}get floorStack(){return o(this,D)}get floor(){return o(this,D).defaultFloor}matchesFloorStack(t){return t===o(this,D)||t===o(this,D).id}show(){b(this,tt,vt).call(this,!0)}hide(){b(this,tt,vt).call(this,!1)}destroy(){this.matchesFloorStack(o(this,H).currentFloorStack)||this.hide()}};D=new WeakMap,H=new WeakMap,tt=new WeakSet,vt=s(function(t){for(let e of o(this,D).floors)o(this,H).updateState(e,{visible:t})},"#setVisible"),s(kt,"Outdoors");var ht=kt;function Ct(r,t){let e=r.find(i=>i.type?.toLowerCase()==="outdoor");if(e)return e;let a=r.find(i=>i.facade==null&&!t.has(i.id));return a||(\$.warn("No good candidate for the outdoor floor stack was found. Using the first floor stack."),r[0])}s(Ct,"getOutdoorFloorStack");var Pt=st("@mappedin/mappedin-js"),Rt={indoorZoomThreshold:18,outdoorZoomThreshold:17,setFloorOnFocus:!0,autoFocus:!1,indoorAnimationOptions:{duration:150},outdoorAnimationOptions:{duration:150},autoAdjustFacadeHeights:!1,mode:"default-floor",preloadFloors:!0,customMultiFloorVisibilityState:Pt.getMultiFloorState,dynamicBuildingInteriors:!0};var v,n,B,d,_,N,h,M,I,L,A,q,T,V,W,x,g,Dt,Tt,ot,et,it,at,K,At,jt,Gt,Z,wt=class wt{constructor(t){u(this,g);u(this,v);u(this,n);u(this,B);u(this,d,Rt);u(this,_,[]);u(this,N,new Set);u(this,h,new Map);u(this,M);u(this,I,!1);u(this,L,!1);u(this,A,0);u(this,q,0);u(this,T,"transition");u(this,V,"outdoor");u(this,W,[]);u(this,x,!1);m(this,"sceneUpdateQueue",Promise.resolve());m(this,"on",s((t,e)=>{o(this,v).on(t,e)},"on"));m(this,"off",s((t,e)=>{o(this,v).off(t,e)},"off"));u(this,ot,s(t=>{if(!this.isEnabled)return;let{facades:e}=t;if(!(Vt(e,this.focusedFacades)&&o(this,V)==="transition"&&!o(this,L))){if(l(this,L,!1),l(this,_,[]),o(this,N).clear(),e.length>0)for(let a of e){let i=o(this,h).get(a.floorStack.id);i&&(o(this,N).add(i.id),o(this,_).push(i))}o(this,d).autoFocus&&this.focus()}},"#handleFacadesInViewChange"));u(this,et,s(async t=>{if(!this.isEnabled)return;let{floor:e}=t,a=o(this,h).get(e.floorStack.id);if(a&&(a.activeFloor=e),a?.excluded===!1&&!o(this,M).matchesFloorStack(e.floorStack)&&l(this,A,e.elevation),o(this,n).manualFloorVisibility===!0){t.reason!=="dynamic-focus"&&(await o(this,Z).call(this,e),o(this,v).publish("focus",{facades:this.focusedFacades}));let i=a?.floorsAltitudesMap.get(e.elevation)?.altitude??0;o(this,n).options.multiFloorView!=null&&o(this,n).options.multiFloorView?.enabled&&o(this,n).options.multiFloorView?.updateCameraElevationOnFloorChange&&o(this,n).Camera.elevation!==i&&o(this,n).Camera.animateElevation(i,{duration:750,easing:"ease-in-out"})}},"#handleFloorChangeStart"));u(this,it,s(()=>{l(this,I,!0)},"#handleUserInteractionStart"));u(this,at,s(()=>{l(this,I,!1)},"#handleUserInteractionEnd"));u(this,K,s(t=>{if(!this.isEnabled)return;let{zoomLevel:e}=t,a=xt(e,o(this,d).indoorZoomThreshold,o(this,d).outdoorZoomThreshold);o(this,T)!==a&&(l(this,T,a),a==="in-range"?this.setIndoor():a==="out-of-range"&&this.setOutdoor())},"#handleCameraChange"));u(this,Z,s(async t=>{if(o(this,n).manualFloorVisibility!==!0||!this.isEnabled)return;let e=t||o(this,n).currentFloor,a=o(this,n).options.multiFloorView,i=o(this,n).Navigation?.floors?.map(p=>p.id)||[],c=o(this,n).Navigation?.floorStacks.map(p=>p.id)||[],y=new Promise(async p=>{await this.sceneUpdateQueue;let z=_t(Array.from(o(this,h).values()),o(this,N),e,o(this,T),o(this,d).mode,o(this,A),i,c,a,o(this,d).customMultiFloorVisibilityState??mt.getMultiFloorState,o(this,d).dynamicBuildingInteriors),rt=[];await Promise.all(Array.from(z.values()).map(async O=>{let{building:C,showIndoor:f,floorStackState:P,facadeState:R,inFocus:Q}=O;rt.push(P);let nt=Nt(C,f);if(nt==="indoor")return b(this,g,jt).call(this,C,P,R,Q);if(nt==="outdoor")return b(this,g,Gt).call(this,C,P,R,c)})),o(this,n).Outdoor.setOpacity(Ot(rt,o(this,d).mode)),l(this,W,o(this,_).filter(O=>z.get(O.id)?.showIndoor===!0).map(O=>O.facade)),o(this,v).publish("focus",{facades:o(this,W)}),p()});return this.sceneUpdateQueue=y,y},"#applyBuildingStates"));l(this,v,new lt),l(this,n,t),\$.setLevel(U.logState),l(this,B,o(this,n).getMapData()),l(this,A,o(this,n).currentFloor.elevation),l(this,q,o(this,n).Camera.elevation);for(let e of o(this,B).getByType("facade"))o(this,h).set(e.floorStack.id,new ut(e.floorStack,o(this,n)));l(this,M,new ht(Ct(o(this,B).getByType("floor-stack"),o(this,h)),o(this,n))),o(this,n).on("floor-change-start",o(this,et)),o(this,n).on("camera-change",o(this,K)),o(this,n).on("facades-in-view-change",o(this,ot)),o(this,n).on("user-interaction-start",o(this,it)),o(this,n).on("user-interaction-end",o(this,at))}enable(t){if(o(this,x)){\$.warn("enable() called on an already enabled Dynamic Focus instance.");return}l(this,x,!0),o(this,n).manualFloorVisibility=!0,o(this,M).show(),this.updateState({...o(this,d),...t}),o(this,K).call(this,{zoomLevel:o(this,n).Camera.zoomLevel,center:o(this,n).Camera.center,bearing:o(this,n).Camera.bearing,pitch:o(this,n).Camera.pitch}),o(this,n).Camera.updateFacadesInView()}disable(){if(!o(this,x)){\$.warn("disable() called on an already disabled Dynamic Focus instance.");return}l(this,x,!1),o(this,n).manualFloorVisibility=!1}get isEnabled(){return o(this,x)}get isIndoor(){return o(this,V)==="indoor"}get isOutdoor(){return o(this,V)==="outdoor"}setIndoor(){l(this,V,"indoor"),l(this,T,"in-range"),b(this,g,Dt).call(this)}setOutdoor(){l(this,V,"outdoor"),l(this,T,"out-of-range"),b(this,g,Dt).call(this)}get focusedFacades(){return[...o(this,W)]}getState(){return{...o(this,d)}}updateState(t){let e=!1;t.indoorZoomThreshold!=null&&(t.indoorZoomThreshold=Et(t.indoorZoomThreshold,t?.outdoorZoomThreshold??o(this,d).outdoorZoomThreshold,o(this,n).Camera.maxZoomLevel,"indoorZoomThreshold"),e=!0),t.outdoorZoomThreshold!=null&&(t.outdoorZoomThreshold=Et(t.outdoorZoomThreshold,o(this,n).Camera.minZoomLevel,t?.indoorZoomThreshold??o(this,d).indoorZoomThreshold,"outdoorZoomThreshold"),e=!0),t.mode!=null&&(t.mode=Lt.includes(t.mode)?t.mode:"default-floor"),t.autoAdjustFacadeHeights!=null&&(o(this,d).autoAdjustFacadeHeights=t.autoAdjustFacadeHeights),t.dynamicBuildingInteriors!=null&&t.dynamicBuildingInteriors!==o(this,d).dynamicBuildingInteriors&&(e=!0),l(this,d,Object.assign({},o(this,d),Object.fromEntries(Object.entries(t).filter(([,a])=>a!=null)))),t.mode!=null&&t.preloadFloors&&b(this,g,Tt).call(this,t.mode),e&&o(this,Z).call(this)}destroy(){this.disable(),o(this,n).off("facades-in-view-change",o(this,ot)),o(this,n).off("floor-change-start",o(this,et)),o(this,n).off("camera-change",o(this,K)),o(this,n).off("user-interaction-start",o(this,it)),o(this,n).off("user-interaction-end",o(this,at)),o(this,h).forEach(t=>t.destroy()),o(this,M).destroy(),o(this,v).destroy()}async focus(t=o(this,d).setFloorOnFocus){if(t)if(It(o(this,q),o(this,n).Camera.elevation,o(this,I)))l(this,q,o(this,n).Camera.elevation),l(this,L,!0);else{let e=Bt(o(this,_),o(this,M),o(this,T)),a=e?dt(e,o(this,d).mode,o(this,A)):void 0;a&&a.id!==o(this,n).currentFloor.id&&o(this,n).setFloor(a,{context:"dynamic-focus"})}await o(this,Z).call(this),o(this,v).publish("focus",{facades:this.focusedFacades})}preloadFloors(){b(this,g,Tt).call(this,o(this,d).mode)}setDefaultFloorForStack(t,e){if(!bt(e,t))return;let a=o(this,h).get(t.id);a&&(a.defaultFloor=e)}resetDefaultFloorForStack(t){let e=o(this,h).get(t.id);e&&(e.defaultFloor=t.defaultFloor)}getDefaultFloorForStack(t){return o(this,h).get(t.id)?.defaultFloor||t.defaultFloor||t.floors[0]}setCurrentFloorForStack(t,e){if(!bt(e,t))return;let a=o(this,h).get(t.id);a&&(a.activeFloor=e,o(this,Z).call(this))}exclude(t){let e=Array.isArray(t)?t:[t];for(let a of e){let i=o(this,h).get(a.id);i&&(i.excluded=!0)}}include(t){let e=Array.isArray(t)?t:[t];for(let a of e){let i=o(this,h).get(a.id);i&&(i.excluded=!1)}}getCurrentFloorForStack(t){return o(this,h).get(t.id)?.activeFloor||this.getDefaultFloorForStack(t)}};v=new WeakMap,n=new WeakMap,B=new WeakMap,d=new WeakMap,_=new WeakMap,N=new WeakMap,h=new WeakMap,M=new WeakMap,I=new WeakMap,L=new WeakMap,A=new WeakMap,q=new WeakMap,T=new WeakMap,V=new WeakMap,W=new WeakMap,x=new WeakMap,g=new WeakSet,Dt=s(function(){o(this,d).autoFocus&&(o(this,I)?this.focus():l(this,L,!0)),o(this,v).publish("state-change")},"#handleViewStateChange"),Tt=s(function(t){o(this,n).preloadFloors(o(this,B).getByType("facade").map(e=>dt(o(this,h).get(e.floorStack.id),t,o(this,A))).filter(e=>e!=null&&mt.Floor.is(e)))},"#preloadFloors"),ot=new WeakMap,et=new WeakMap,it=new WeakMap,at=new WeakMap,K=new WeakMap,At=s(function(t,e,a){t.forEach(i=>{if(i.floor)if(e){let c=a!==void 0?{...i.state,labels:{...i.state.labels,enabled:i.state.labels.enabled&&a},markers:{...i.state.markers,enabled:i.state.markers.enabled&&a},occlusion:{...i.state.occlusion,enabled:i.state.occlusion.enabled&&a}}:i.state;o(this,n).updateState(i.floor,c)}else o(this,n).updateState(i.floor,{visible:!1})})},"#updateFloorVisibility"),jt=s(async function(t,e,a,i){return b(this,g,At).call(this,e.floorStates,!0,i),t.animateFacade(a.state,o(this,d).indoorAnimationOptions)},"#animateIndoorSequence"),Gt=s(async function(t,e,a,i){let c=await t.animateFacade(a.state,o(this,d).outdoorAnimationOptions);return c.result==="completed"&&b(this,g,At).call(this,e.floorStates,yt(t,o(this,n).currentFloor,o(this,T)==="in-range",o(this,N).has(t.id),o(this,d).mode,o(this,A),i.includes(t.floorStack.id),o(this,d).dynamicBuildingInteriors)),c},"#animateOutdoorSequence"),Z=new WeakMap,s(wt,"DynamicFocus");var ft=wt;return zt(oo);})();
105
105
  //# sourceMappingURL=dynamic-focus.iife.js.map
106
106
 
107
107
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mappedin/dynamic-focus",
3
- "version": "6.0.1-beta.59",
3
+ "version": "6.0.1-beta.61",
4
4
  "homepage": "https://developer.mappedin.com/",
5
5
  "private": false,
6
6
  "main": "lib/esm/index.js",
@@ -37,9 +37,9 @@
37
37
  "license": "SEE LICENSE IN LICENSE.txt",
38
38
  "peerDependencies": {
39
39
  "react": ">=16.8.0",
40
- "@mappedin/mappedin-js": "^6.1.0",
41
- "@mappedin/react-native-sdk": "^6.1.0",
42
- "@mappedin/react-sdk": "^6.1.0"
40
+ "@mappedin/mappedin-js": "^6.1.2",
41
+ "@mappedin/react-sdk": "^6.1.2",
42
+ "@mappedin/react-native-sdk": "^6.1.2"
43
43
  },
44
44
  "peerDependenciesMeta": {
45
45
  "@mappedin/react-sdk": {
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["<define:process>", "../../src/dynamic-focus.ts", "../../../packages/common/array-utils.ts", "../../../packages/common/pubsub.ts", "../../src/building.ts", "../../src/dynamic-focus-scene.ts", "../../src/types.ts", "../../src/validation.ts", "../../../packages/common/Mappedin.Logger.ts", "../../../packages/common/math-utils.ts", "../../src/logger.ts", "../../src/outdoors.ts", "../../src/constants.ts"],
4
- "sourcesContent": ["{\"env\":{\"npm_package_version\":\"6.0.1-beta.59\"}}", "import type {\n\tCameraTransform,\n\tFacade,\n\tFloorStack,\n\tMapData,\n\tMapView,\n\tTEvents,\n\tTFloorState,\n} from '@mappedin/mappedin-js';\nimport { Floor, getMultiFloorState } from '@mappedin/mappedin-js';\nimport { arraysEqual } from '@packages/internal/common/array-utils';\nimport { PubSub } from '@packages/internal/common/pubsub';\nimport { Building } from './building';\nimport {\n\tgetFloorToShow,\n\tshouldShowIndoor,\n\tgetBuildingAnimationType,\n\tgetZoomState,\n\tgetOutdoorOpacity,\n\tgetSetFloorTargetFromZoomState,\n\tgetBuildingStates,\n\tshouldDeferSetFloor,\n} from './dynamic-focus-scene';\nimport { DYNAMIC_FOCUS_MODES } from './types';\nimport type {\n\tViewState,\n\tZoomState,\n\tBuildingFacadeState,\n\tDynamicFocusEventPayload,\n\tDynamicFocusEvents,\n\tDynamicFocusMode,\n\tDynamicFocusState,\n\tBuildingFloorStackState,\n\tInternalDynamicFocusEvents,\n} from './types';\nimport { validateFloorForStack, validateZoomThreshold } from './validation';\nimport { getOutdoorFloorStack, Outdoors } from './outdoors';\nimport { Logger } from './logger';\nimport MappedinJSLogger from '../../packages/common/Mappedin.Logger';\nimport { DEFAULT_STATE } from './constants';\nimport type { MapViewExtension } from '@packages/internal/common/extensions';\n\n/**\n * Dynamic Focus is a MapView scene manager that maintains the visibility of the outdoors\n * while fading in and out building interiors as the camera pans.\n */\nexport class DynamicFocus implements MapViewExtension<DynamicFocusState> {\n\t#pubsub: PubSub<DynamicFocusEvents & InternalDynamicFocusEvents>;\n\t#mapView: MapView;\n\t#mapData: MapData;\n\t#state: Required<DynamicFocusState> = DEFAULT_STATE;\n\t/**\n\t * The buildings that are currently in view, sorted by the order they are in the facades-in-view-change event.\n\t * While these will be within the camera view, these may not be in focus or showIndoor depending on the mode.\n\t */\n\t#sortedBuildingsInView: Building[] = [];\n\t/**\n\t * The buildings that are currently in view, as a set of building ids.\n\t */\n\t#buildingIdsInViewSet = new Set<string>();\n\t#buildings = new Map<string, Building>();\n\t#outdoors: Outdoors;\n\t#userInteracting = false;\n\t#pendingFacadeUpdate = false;\n\t#floorElevation = 0;\n\t#cameraElevation = 0;\n\t/**\n\t * Tracks the current zoom state based on camera zoom level:\n\t * - 'in-range': Camera is zoomed in enough to show indoor details (>= indoorZoomThreshold)\n\t * - 'out-of-range': Camera is zoomed out to show outdoor context (<= outdoorZoomThreshold)\n\t * - 'transition': Camera is between the two thresholds (no floor changes occur)\n\t */\n\t#zoomState: ZoomState = 'transition';\n\t#viewState: ViewState = 'outdoor';\n\t/**\n\t * The facades that are actually focused and shown (filtered by showIndoor logic)\n\t */\n\t#facadesInFocus: Facade[] = [];\n\t#enabled = false;\n\n\t/**\n\t * @internal\n\t * Used to await the current scene update before starting a new one, or when the scene is updated asynchronously by an event.\n\t */\n\tprivate sceneUpdateQueue: Promise<void> = Promise.resolve();\n\n\t/**\n\t * Creates a new instance of the Dynamic Focus controller.\n\t *\n\t * @param mapView - The {@link MapView} to attach Dynamic Focus to.\n\t * @param options - Options for configuring Dynamic Focus.\n\t *\n\t * @example\n\t * ```ts\n\t * const mapView = show3dMap(...);\n\t * const df = new DynamicFocus(mapView);\n\t * df.enable({ autoFocus: true });\n\t *\n\t * // pause the listener\n\t * df.updateState({ autoFocus: false });\n\t *\n\t * // manually trigger a focus\n\t * df.focus();\n\t * ```\n\t */\n\tconstructor(mapView: MapView) {\n\t\tthis.#pubsub = new PubSub<DynamicFocusEvents & InternalDynamicFocusEvents>();\n\t\tthis.#mapView = mapView;\n\t\tLogger.setLevel(MappedinJSLogger.logState);\n\t\tthis.#mapData = this.#mapView.getMapData();\n\t\tthis.#floorElevation = this.#mapView.currentFloor.elevation;\n\t\tthis.#cameraElevation = this.#mapView.Camera.elevation;\n\t\t// initialize the buildings\n\t\tfor (const facade of this.#mapData.getByType('facade')) {\n\t\t\tthis.#buildings.set(facade.floorStack.id, new Building(facade.floorStack, this.#mapView));\n\t\t}\n\t\tthis.#outdoors = new Outdoors(\n\t\t\tgetOutdoorFloorStack(this.#mapData.getByType('floor-stack'), this.#buildings),\n\t\t\tthis.#mapView,\n\t\t);\n\t\tthis.#mapView.on('floor-change-start', this.#handleFloorChangeStart);\n\t\tthis.#mapView.on('camera-change', this.#handleCameraChange);\n\t\tthis.#mapView.on('facades-in-view-change', this.#handleFacadesInViewChange);\n\t\tthis.#mapView.on('user-interaction-start', this.#handleUserInteractionStart);\n\t\tthis.#mapView.on('user-interaction-end', this.#handleUserInteractionEnd);\n\t}\n\n\t/**\n\t * Enables Dynamic Focus with the given options.\n\t * @param options - The options to enable Dynamic Focus with.\n\t */\n\tenable(options?: Partial<DynamicFocusState>): void {\n\t\tif (this.#enabled) {\n\t\t\tLogger.warn('enable() called on an already enabled Dynamic Focus instance.');\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#enabled = true;\n\t\tthis.#mapView.manualFloorVisibility = true;\n\t\tthis.#outdoors.show();\n\t\tthis.updateState({ ...this.#state, ...options });\n\t\t// fire the camera change event to set the initial state\n\t\tthis.#handleCameraChange({\n\t\t\tzoomLevel: this.#mapView.Camera.zoomLevel,\n\t\t\tcenter: this.#mapView.Camera.center,\n\t\t\tbearing: this.#mapView.Camera.bearing,\n\t\t\tpitch: this.#mapView.Camera.pitch,\n\t\t} as CameraTransform);\n\t\t// fire dynamic focus change to set initial state of facades\n\t\tthis.#mapView.Camera.updateFacadesInView();\n\t}\n\t/**\n\t * Disables Dynamic Focus and returns the MapView to it's previous state.\n\t */\n\tdisable(): void {\n\t\tif (!this.#enabled) {\n\t\t\tLogger.warn('disable() called on an already disabled Dynamic Focus instance.');\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#enabled = false;\n\t\tthis.#mapView.manualFloorVisibility = false;\n\t}\n\n\t/**\n\t * Returns true if Dynamic Focus is enabled.\n\t */\n\tget isEnabled(): boolean {\n\t\treturn this.#enabled;\n\t}\n\n\t/**\n\t * Returns true if the current view state is indoor.\n\t */\n\tget isIndoor() {\n\t\treturn this.#viewState === 'indoor';\n\t}\n\n\t/**\n\t * Returns true if the current view state is outdoor.\n\t */\n\tget isOutdoor() {\n\t\treturn this.#viewState === 'outdoor';\n\t}\n\n\t/**\n\t * Sets the view state to indoor, regardless of the current zoom level.\n\t */\n\tsetIndoor() {\n\t\tthis.#viewState = 'indoor';\n\t\tthis.#zoomState = 'in-range';\n\n\t\tthis.#handleViewStateChange();\n\t}\n\n\t/**\n\t * Sets the view state to outdoor, regardless of the current zoom level.\n\t */\n\tsetOutdoor() {\n\t\tthis.#viewState = 'outdoor';\n\t\tthis.#zoomState = 'out-of-range';\n\n\t\tthis.#handleViewStateChange();\n\t}\n\n\t#handleViewStateChange() {\n\t\tif (this.#state.autoFocus) {\n\t\t\t// Only set the floor if setFloorOnFocus is true and the view state changed due to a user interaction\n\t\t\t// Camera animations will not trigger a focus change until they settle.\n\t\t\tif (this.#userInteracting) {\n\t\t\t\tthis.focus();\n\t\t\t} else {\n\t\t\t\tthis.#pendingFacadeUpdate = true;\n\t\t\t}\n\t\t}\n\t\tthis.#pubsub.publish('state-change');\n\t}\n\n\t#preloadFloors(mode: DynamicFocusMode) {\n\t\tthis.#mapView.preloadFloors(\n\t\t\tthis.#mapData\n\t\t\t\t.getByType('facade')\n\t\t\t\t.map(facade => getFloorToShow(this.#buildings.get(facade.floorStack.id)!, mode, this.#floorElevation))\n\t\t\t\t.filter(f => f != null && Floor.is(f)),\n\t\t);\n\t}\n\n\t/**\n\t * Returns the facades that are currently in focus.\n\t */\n\tget focusedFacades() {\n\t\treturn [...this.#facadesInFocus];\n\t}\n\n\t/**\n\t * Subscribe to a Dynamic Focus event.\n\t */\n\ton = <EventName extends keyof DynamicFocusEvents>(\n\t\teventName: EventName,\n\t\tfn: (payload: DynamicFocusEventPayload<EventName>) => void,\n\t) => {\n\t\tthis.#pubsub.on(eventName, fn);\n\t};\n\n\t/**\n\t * Unsubscribe from a Dynamic Focus event.\n\t */\n\toff = <EventName extends keyof DynamicFocusEvents>(\n\t\teventName: EventName,\n\t\tfn: (payload: DynamicFocusEventPayload<EventName>) => void,\n\t) => {\n\t\tthis.#pubsub.off(eventName, fn);\n\t};\n\n\t/**\n\t * Returns the current state of the Dynamic Focus controller.\n\t */\n\tgetState(): DynamicFocusState {\n\t\treturn { ...this.#state };\n\t}\n\n\t/**\n\t * Updates the state of the Dynamic Focus controller.\n\t * @param state - The state to update.\n\t */\n\tupdateState(state: Partial<DynamicFocusState>) {\n\t\tlet shouldReapplyBuildingStates = false;\n\n\t\tif (state.indoorZoomThreshold != null) {\n\t\t\tstate.indoorZoomThreshold = validateZoomThreshold(\n\t\t\t\tstate.indoorZoomThreshold,\n\t\t\t\tthis.#state.outdoorZoomThreshold,\n\t\t\t\tthis.#mapView.Camera.maxZoomLevel,\n\t\t\t\t'indoorZoomThreshold',\n\t\t\t);\n\t\t}\n\t\tif (state.outdoorZoomThreshold != null) {\n\t\t\tstate.outdoorZoomThreshold = validateZoomThreshold(\n\t\t\t\tstate.outdoorZoomThreshold,\n\t\t\t\tthis.#mapView.Camera.minZoomLevel,\n\t\t\t\tthis.#state.indoorZoomThreshold,\n\t\t\t\t'outdoorZoomThreshold',\n\t\t\t);\n\t\t}\n\n\t\tif (state.mode != null) {\n\t\t\tstate.mode = DYNAMIC_FOCUS_MODES.includes(state.mode) ? state.mode : 'default-floor';\n\t\t}\n\n\t\tif (state.autoAdjustFacadeHeights != null) {\n\t\t\tthis.#state.autoAdjustFacadeHeights = state.autoAdjustFacadeHeights;\n\t\t}\n\n\t\tif (\n\t\t\tstate.dynamicBuildingInteriors != null &&\n\t\t\tstate.dynamicBuildingInteriors !== this.#state.dynamicBuildingInteriors\n\t\t) {\n\t\t\tshouldReapplyBuildingStates = true;\n\t\t}\n\n\t\t// assign state and ignore undefined values\n\t\tthis.#state = Object.assign(\n\t\t\t{},\n\t\t\tthis.#state,\n\t\t\tObject.fromEntries(Object.entries(state).filter(([, value]) => value != null)),\n\t\t);\n\n\t\t// preload the initial floors that will be included in the mode\n\t\tif (state.mode != null && state.preloadFloors) {\n\t\t\tthis.#preloadFloors(state.mode);\n\t\t}\n\n\t\tif (shouldReapplyBuildingStates) {\n\t\t\tthis.#applyBuildingStates();\n\t\t}\n\t}\n\n\t/**\n\t * Destroys the Dynamic Focus instance and unsubscribes all MapView event listeners.\n\t */\n\tdestroy() {\n\t\tthis.disable();\n\t\tthis.#mapView.off('facades-in-view-change', this.#handleFacadesInViewChange);\n\t\tthis.#mapView.off('floor-change-start', this.#handleFloorChangeStart);\n\t\tthis.#mapView.off('camera-change', this.#handleCameraChange);\n\t\tthis.#mapView.off('user-interaction-start', this.#handleUserInteractionStart);\n\t\tthis.#mapView.off('user-interaction-end', this.#handleUserInteractionEnd);\n\t\tthis.#buildings.forEach(building => building.destroy());\n\t\tthis.#outdoors.destroy();\n\t\tthis.#pubsub.destroy();\n\t}\n\n\t/**\n\t * Perform a manual visual update of the focused facades, and optionally set the floor.\n\t * @param setFloor - Whether to set the floor. This will default to the current state of setFloorOnFocus.\n\t */\n\tasync focus(setFloor = this.#state.setFloorOnFocus) {\n\t\tif (setFloor) {\n\t\t\tif (shouldDeferSetFloor(this.#cameraElevation, this.#mapView.Camera.elevation, this.#userInteracting)) {\n\t\t\t\tthis.#cameraElevation = this.#mapView.Camera.elevation;\n\t\t\t\tthis.#pendingFacadeUpdate = true;\n\t\t\t} else {\n\t\t\t\tconst target = getSetFloorTargetFromZoomState(this.#sortedBuildingsInView, this.#outdoors, this.#zoomState);\n\n\t\t\t\tconst floor = target ? getFloorToShow(target, this.#state.mode, this.#floorElevation) : undefined;\n\n\t\t\t\tif (floor && floor.id !== this.#mapView.currentFloor.id) {\n\t\t\t\t\tthis.#mapView.setFloor(floor, { context: 'dynamic-focus' });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tawait this.#applyBuildingStates();\n\t\t// must publish after the scene is updated to ensure the focusedFacades array is up to date\n\t\tthis.#pubsub.publish('focus', { facades: this.focusedFacades });\n\t}\n\n\t/**\n\t * Preloads the initial floors for each building to improve performance when rendering the building for the first time. See {@link DynamicFocusState.preloadFloors}.\n\t */\n\tpreloadFloors() {\n\t\tthis.#preloadFloors(this.#state.mode);\n\t}\n\n\t/**\n\t * Sets the default floor for a floor stack. This is the floor that will be shown when focusing on a facade if there is no currently active floor in the stack.\n\t * See {@link resetDefaultFloorForStack} to reset the default floor.\n\t * @param floorStack - The floor stack to set the default floor for.\n\t * @param floor - The floor to set as the default floor.\n\t */\n\tsetDefaultFloorForStack(floorStack: FloorStack, floor: Floor) {\n\t\tif (!validateFloorForStack(floor, floorStack)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst building = this.#buildings.get(floorStack.id);\n\t\tif (building) {\n\t\t\tbuilding.defaultFloor = floor;\n\t\t}\n\t}\n\n\t/**\n\t * Resets the default floor for a floor stack to it's initial value.\n\t * @param floorStack - The floor stack to reset the default floor for.\n\t */\n\tresetDefaultFloorForStack(floorStack: FloorStack) {\n\t\tconst building = this.#buildings.get(floorStack.id);\n\t\tif (building) {\n\t\t\tbuilding.defaultFloor = floorStack.defaultFloor;\n\t\t}\n\t}\n\n\t/**\n\t * Returns the current default floor for a floor stack.\n\t * @param floorStack - The floor stack to get the default floor for.\n\t * @returns The current default floor for the floor stack.\n\t */\n\tgetDefaultFloorForStack(floorStack: FloorStack) {\n\t\treturn this.#buildings.get(floorStack.id)?.defaultFloor || floorStack.defaultFloor || floorStack.floors[0];\n\t}\n\n\t/**\n\t * Sets the current floor for a floor stack. If the floor stack is currently focused, this floor will become visible.\n\t * @param floorStack - The floor stack to set the current floor for.\n\t */\n\tsetCurrentFloorForStack(floorStack: FloorStack, floor: Floor) {\n\t\tif (!validateFloorForStack(floor, floorStack)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst building = this.#buildings.get(floorStack.id);\n\t\tif (building) {\n\t\t\tbuilding.activeFloor = floor;\n\t\t\tthis.#applyBuildingStates();\n\t\t}\n\t}\n\n\t/**\n\t * Excludes a floor stack from visibility changes.\n\t * @param excluded - The floor stack or stacks to exclude.\n\t */\n\texclude(excluded: FloorStack | FloorStack[]) {\n\t\tconst excludedFloorStacks = Array.isArray(excluded) ? excluded : [excluded];\n\t\tfor (const floorStack of excludedFloorStacks) {\n\t\t\tconst building = this.#buildings.get(floorStack.id);\n\t\t\tif (building) {\n\t\t\t\tbuilding.excluded = true;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Includes a floor stack in visibility changes.\n\t * @param included - The floor stack or stacks to include.\n\t */\n\tinclude(included: FloorStack | FloorStack[]) {\n\t\tconst includedFloorStacks = Array.isArray(included) ? included : [included];\n\t\tfor (const floorStack of includedFloorStacks) {\n\t\t\tconst building = this.#buildings.get(floorStack.id);\n\t\t\tif (building) {\n\t\t\t\tbuilding.excluded = false;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Returns the current floor for a floor stack.\n\t * @param floorStack - The floor stack to get the current floor for.\n\t * @returns The current floor for the floor stack.\n\t */\n\tgetCurrentFloorForStack(floorStack: FloorStack) {\n\t\treturn this.#buildings.get(floorStack.id)?.activeFloor || this.getDefaultFloorForStack(floorStack);\n\t}\n\n\t/**\n\t * Handles management of focused facades but doesn't trigger view updates unless enabled.\n\t * @see {@link focus} to manually trigger a view update.\n\t */\n\t#handleFacadesInViewChange = (event: TEvents['facades-in-view-change']) => {\n\t\tif (!this.isEnabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { facades } = event;\n\n\t\t// if the facades are the same, or we're in between outdoor/indoor, don't do anything unless we're pending a facade update\n\t\tif (arraysEqual(facades, this.focusedFacades) && this.#viewState === 'transition' && !this.#pendingFacadeUpdate) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#pendingFacadeUpdate = false;\n\n\t\tthis.#sortedBuildingsInView = [];\n\t\tthis.#buildingIdsInViewSet.clear();\n\t\tif (facades.length > 0) {\n\t\t\tfor (const facade of facades) {\n\t\t\t\tconst building = this.#buildings.get(facade.floorStack.id);\n\t\t\t\tif (building) {\n\t\t\t\t\tthis.#buildingIdsInViewSet.add(building.id);\n\t\t\t\t\tthis.#sortedBuildingsInView.push(building);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.#state.autoFocus) {\n\t\t\tthis.focus();\n\t\t}\n\t};\n\t/**\n\t * Handles floor and facade visibility when the floor changes.\n\t */\n\t#handleFloorChangeStart = async (event: TEvents['floor-change-start']) => {\n\t\tif (!this.isEnabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { floor: newFloor } = event;\n\t\tconst building = this.#buildings.get(newFloor.floorStack.id);\n\t\tif (building) {\n\t\t\tbuilding.activeFloor = newFloor;\n\t\t}\n\t\t// Don't update elevation when switching to outdoor floor stack\n\t\tif (building?.excluded === false && !this.#outdoors.matchesFloorStack(newFloor.floorStack)) {\n\t\t\tthis.#floorElevation = newFloor.elevation;\n\t\t}\n\n\t\tif (this.#mapView.manualFloorVisibility === true) {\n\t\t\tif (event.reason !== 'dynamic-focus') {\n\t\t\t\tawait this.#applyBuildingStates(newFloor);\n\t\t\t\t// Despite this not really being a focus event, we've changed the focused facades, so we need to publish it\n\t\t\t\tthis.#pubsub.publish('focus', { facades: this.focusedFacades });\n\t\t\t}\n\n\t\t\tconst altitude = building?.floorsAltitudesMap.get(newFloor.elevation)?.altitude ?? 0;\n\t\t\tif (\n\t\t\t\tthis.#mapView.options.multiFloorView != null &&\n\t\t\t\tthis.#mapView.options.multiFloorView?.enabled &&\n\t\t\t\tthis.#mapView.options.multiFloorView?.updateCameraElevationOnFloorChange &&\n\t\t\t\tthis.#mapView.Camera.elevation !== altitude\n\t\t\t) {\n\t\t\t\tthis.#mapView.Camera.animateElevation(altitude, {\n\t\t\t\t\tduration: 750,\n\t\t\t\t\teasing: 'ease-in-out',\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t};\n\n\t#handleUserInteractionStart = () => {\n\t\tthis.#userInteracting = true;\n\t};\n\t#handleUserInteractionEnd = () => {\n\t\tthis.#userInteracting = false;\n\t};\n\n\t/**\n\t * Handles camera moving in and out of zoom range and fires a focus event if the camera is in range.\n\t */\n\t#handleCameraChange = (event: TEvents['camera-change']) => {\n\t\tif (!this.isEnabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { zoomLevel } = event;\n\t\tconst newZoomState = getZoomState(zoomLevel, this.#state.indoorZoomThreshold, this.#state.outdoorZoomThreshold);\n\n\t\tif (this.#zoomState !== newZoomState) {\n\t\t\tthis.#zoomState = newZoomState;\n\n\t\t\tif (newZoomState === 'in-range') {\n\t\t\t\tthis.setIndoor();\n\t\t\t} else if (newZoomState === 'out-of-range') {\n\t\t\t\tthis.setOutdoor();\n\t\t\t}\n\t\t}\n\t};\n\n\t#updateFloorVisibility(floorStates: BuildingFloorStackState['floorStates'], shouldShow: boolean, inFocus?: boolean) {\n\t\tfloorStates.forEach(floorState => {\n\t\t\tif (floorState.floor) {\n\t\t\t\tif (shouldShow) {\n\t\t\t\t\tconst state =\n\t\t\t\t\t\tinFocus !== undefined\n\t\t\t\t\t\t\t? ({\n\t\t\t\t\t\t\t\t\t...floorState.state,\n\t\t\t\t\t\t\t\t\tlabels: {\n\t\t\t\t\t\t\t\t\t\t...floorState.state.labels,\n\t\t\t\t\t\t\t\t\t\tenabled: floorState.state.labels.enabled && inFocus,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tmarkers: {\n\t\t\t\t\t\t\t\t\t\t...floorState.state.markers,\n\t\t\t\t\t\t\t\t\t\tenabled: floorState.state.markers.enabled && inFocus,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tocclusion: {\n\t\t\t\t\t\t\t\t\t\t...floorState.state.occlusion,\n\t\t\t\t\t\t\t\t\t\t// We don't want this floor to occlude if it's not in focus\n\t\t\t\t\t\t\t\t\t\t// Allows us to show a label above this floor while it's not active\n\t\t\t\t\t\t\t\t\t\tenabled: floorState.state.occlusion.enabled && inFocus,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t } satisfies TFloorState)\n\t\t\t\t\t\t\t: floorState.state;\n\n\t\t\t\t\tthis.#mapView.updateState(floorState.floor, state);\n\t\t\t\t} else {\n\t\t\t\t\tthis.#mapView.updateState(floorState.floor, { visible: false });\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tasync #animateIndoorSequence(\n\t\tbuilding: Building,\n\t\tfloorStackState: BuildingFloorStackState,\n\t\tfacadeState: BuildingFacadeState,\n\t\tinFocus: boolean,\n\t) {\n\t\t// show floor first then fade in the facade\n\t\tthis.#updateFloorVisibility(floorStackState.floorStates, true, inFocus);\n\n\t\treturn building.animateFacade(facadeState.state, this.#state.indoorAnimationOptions);\n\t}\n\n\tasync #animateOutdoorSequence(\n\t\tbuilding: Building,\n\t\tfloorStackState: BuildingFloorStackState,\n\t\tfacadeState: BuildingFacadeState,\n\t\tfloorStackIdsInNavigation: string[],\n\t) {\n\t\t// fade in facade then hide floors when complete\n\t\tconst result = await building.animateFacade(facadeState.state, this.#state.outdoorAnimationOptions);\n\n\t\tif (result.result === 'completed') {\n\t\t\t// Re-check if we should still show indoor after animation completes\n\t\t\tthis.#updateFloorVisibility(\n\t\t\t\tfloorStackState.floorStates,\n\t\t\t\tshouldShowIndoor(\n\t\t\t\t\tbuilding,\n\t\t\t\t\tthis.#mapView.currentFloor,\n\t\t\t\t\tthis.#zoomState === 'in-range',\n\t\t\t\t\tthis.#buildingIdsInViewSet.has(building.id),\n\t\t\t\t\tthis.#state.mode,\n\t\t\t\t\tthis.#floorElevation,\n\t\t\t\t\tfloorStackIdsInNavigation.includes(building.floorStack.id),\n\t\t\t\t\tthis.#state.dynamicBuildingInteriors,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t#applyBuildingStates = async (newFloor?: Floor) => {\n\t\tif (this.#mapView.manualFloorVisibility !== true || !this.isEnabled) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentFloor = newFloor || this.#mapView.currentFloor;\n\t\tconst multiFloorView = this.#mapView.options.multiFloorView;\n\t\tconst floorIdsInNavigation = this.#mapView.Navigation?.floors?.map(f => f.id) || [];\n\t\tconst floorStackIdsInNavigation = this.#mapView.Navigation?.floorStacks.map(fs => fs.id) || [];\n\n\t\t// Create a new promise for this update\n\t\tconst updatePromise = new Promise<void>(async resolve => {\n\t\t\t// Wait for the previous update to complete\n\t\t\tawait this.sceneUpdateQueue;\n\n\t\t\tconst buildingStates = getBuildingStates(\n\t\t\t\tArray.from(this.#buildings.values()),\n\t\t\t\tthis.#buildingIdsInViewSet,\n\t\t\t\tcurrentFloor,\n\t\t\t\tthis.#zoomState,\n\t\t\t\tthis.#state.mode,\n\t\t\t\tthis.#floorElevation,\n\t\t\t\tfloorIdsInNavigation,\n\t\t\t\tfloorStackIdsInNavigation,\n\t\t\t\tmultiFloorView,\n\t\t\t\tthis.#state.customMultiFloorVisibilityState ?? getMultiFloorState,\n\t\t\t\tthis.#state.dynamicBuildingInteriors,\n\t\t\t);\n\n\t\t\tconst floorStackStates: BuildingFloorStackState[] = [];\n\t\t\tawait Promise.all(\n\t\t\t\tArray.from(buildingStates.values()).map(async buildingState => {\n\t\t\t\t\tconst { building, showIndoor, floorStackState, facadeState, inFocus } = buildingState;\n\n\t\t\t\t\tfloorStackStates.push(floorStackState);\n\n\t\t\t\t\tconst animation = getBuildingAnimationType(building, showIndoor);\n\n\t\t\t\t\tif (animation === 'indoor') {\n\t\t\t\t\t\treturn this.#animateIndoorSequence(building, floorStackState, facadeState, inFocus);\n\t\t\t\t\t} else if (animation === 'outdoor') {\n\t\t\t\t\t\treturn this.#animateOutdoorSequence(building, floorStackState, facadeState, floorStackIdsInNavigation);\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t);\n\n\t\t\tthis.#mapView.Outdoor.setOpacity(getOutdoorOpacity(floorStackStates, this.#state.mode));\n\n\t\t\t// Filter #facadesInFocus to maintain sort order, keeping only buildings with showIndoor true\n\t\t\tthis.#facadesInFocus = this.#sortedBuildingsInView\n\t\t\t\t.filter(building => buildingStates.get(building.id)?.showIndoor === true)\n\t\t\t\t.map(building => building.facade);\n\n\t\t\tthis.#pubsub.publish('focus', { facades: this.#facadesInFocus });\n\n\t\t\tresolve();\n\t\t});\n\n\t\t// Update the queue with the new promise\n\t\tthis.sceneUpdateQueue = updatePromise;\n\n\t\treturn updatePromise;\n\t};\n}\n", "/**\n * Compare two arrays for equality\n */\nexport function arraysEqual(arr1: any[] | null | undefined, arr2: any[] | null | undefined) {\n\tif (arr1 == null || arr2 == null) {\n\t\treturn arr1 === arr2;\n\t}\n\n\tif (arr1.length !== arr2.length) {\n\t\treturn false;\n\t}\n\n\tfor (let i = 0; i < arr1.length; i++) {\n\t\tif (arr1[i] !== arr2[i]) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n", "/**\n * Generic PubSub class implementing the Publish-Subscribe pattern for event handling.\n *\n * @template EVENT_PAYLOAD - The type of the event payload.\n * @template EVENT - The type of the event.\n */\nexport class PubSub<EVENT_PAYLOAD, EVENT extends keyof EVENT_PAYLOAD = keyof EVENT_PAYLOAD> {\n\t/**\n\t * @private\n\t * @internal\n\t */\n\tprivate _subscribers: any = {};\n\t/**\n\t * @private\n\t * @internal\n\t */\n\tprivate _destroyed = false;\n\n\t/**\n\t * @private\n\t * @internal\n\t */\n\tpublish<EVENT_NAME extends EVENT>(eventName: EVENT_NAME, data?: EVENT_PAYLOAD[EVENT_NAME]) {\n\t\tif (!this._subscribers || !this._subscribers[eventName] || this._destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._subscribers[eventName]!.forEach(function (fn) {\n\t\t\tif (typeof fn !== 'function') {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfn(data);\n\t\t});\n\t}\n\n\t/**\n\t * Subscribe a function to an event.\n\t *\n\t * @param eventName An event name which, when fired, will call the provided\n\t * function.\n\t * @param fn A callback that gets called when the corresponding event is fired. The\n\t * callback will get passed an argument with a type that's one of event payloads.\n\t * @example\n\t * // Subscribe to the 'click' event\n\t * const handler = (event) => {\n\t * const { coordinate } = event;\n\t * const { latitude, longitude } = coordinate;\n\t * \tconsole.log(`Map was clicked at ${latitude}, ${longitude}`);\n\t * };\n\t * map.on('click', handler);\n\t */\n\ton<EVENT_NAME extends EVENT>(\n\t\teventName: EVENT_NAME,\n\t\tfn: (\n\t\t\tpayload: EVENT_PAYLOAD[EVENT_NAME] extends {\n\t\t\t\tdata: null;\n\t\t\t}\n\t\t\t\t? EVENT_PAYLOAD[EVENT_NAME]['data']\n\t\t\t\t: EVENT_PAYLOAD[EVENT_NAME],\n\t\t) => void,\n\t) {\n\t\tif (!this._subscribers || this._destroyed) {\n\t\t\tthis._subscribers = {};\n\t\t}\n\t\tthis._subscribers[eventName] = this._subscribers[eventName] || [];\n\t\tthis._subscribers[eventName]!.push(fn);\n\t}\n\n\t/**\n\t * Unsubscribe a function previously subscribed with {@link on}\n\t *\n\t * @param eventName An event name to which the provided function was previously\n\t * subscribed.\n\t * @param fn A function that was previously passed to {@link on}. The function must\n\t * have the same reference as the function that was subscribed.\n\t * @example\n\t * // Unsubscribe from the 'click' event\n\t * const handler = (event) => {\n\t * \tconsole.log('Map was clicked', event);\n\t * };\n\t * map.off('click', handler);\n\t */\n\toff<EVENT_NAME extends EVENT>(\n\t\teventName: EVENT_NAME,\n\t\tfn: (\n\t\t\tpayload: EVENT_PAYLOAD[EVENT_NAME] extends {\n\t\t\t\tdata: null;\n\t\t\t}\n\t\t\t\t? EVENT_PAYLOAD[EVENT_NAME]['data']\n\t\t\t\t: EVENT_PAYLOAD[EVENT_NAME],\n\t\t) => void,\n\t) {\n\t\tif (!this._subscribers || this._subscribers[eventName] == null || this._destroyed) {\n\t\t\treturn;\n\t\t}\n\t\tconst itemIdx = this._subscribers[eventName]!.indexOf(fn);\n\n\t\tif (itemIdx !== -1) {\n\t\t\tthis._subscribers[eventName]!.splice(itemIdx, 1);\n\t\t}\n\t}\n\t/**\n\t * @private\n\t * @internal\n\t */\n\tdestroy() {\n\t\tthis._destroyed = true;\n\t\tthis._subscribers = {};\n\t}\n}\n", "import type { MapView, TAnimateStateResult, TFacadeState } from '@mappedin/mappedin-js';\nimport { Facade, Floor, FloorStack } from '@mappedin/mappedin-js';\nimport type { DynamicFocusAnimationOptions } from './types';\n\nexport class Building {\n\t__type = 'building';\n\t#floorStack: FloorStack;\n\t#floorsById = new Map<string, Floor>();\n\t#floorsByElevation = new Map<number, Floor>();\n\t#floorsByElevationSorted: Floor[] = [];\n\t#mapView: MapView;\n\t#animationInProgress: { state: TFacadeState; animation: ReturnType<MapView['animateState']> } | undefined;\n\n\tdefaultFloor: Floor;\n\tactiveFloor: Floor;\n\texcluded = false;\n\tfloorsAltitudesMap: Map<number, { altitude: number; effectiveHeight: number }> = new Map();\n\taboveGroundFloors: Floor[] = [];\n\n\tconstructor(floorStack: FloorStack, mapView: MapView) {\n\t\tthis.#floorStack = floorStack;\n\t\tthis.#floorsById = new Map(floorStack.floors.map(floor => [floor.id, floor]));\n\t\tthis.#floorsByElevation = new Map(floorStack.floors.map(floor => [floor.elevation, floor]));\n\t\tthis.#floorsByElevationSorted = Array.from(this.#floorsByElevation.values()).sort(\n\t\t\t(a, b) => a.elevation - b.elevation,\n\t\t);\n\t\tthis.defaultFloor = floorStack.defaultFloor;\n\t\tthis.activeFloor = this.defaultFloor;\n\t\tthis.#mapView = mapView;\n\t\tthis.aboveGroundFloors = this.#floorsByElevationSorted.filter(floor => floor.elevation >= 0);\n\n\t\tconst sortedSpaces = floorStack.facade?.spaces\n\t\t\t.map(space => this.#mapView.getState(space))\n\t\t\t.sort((a, b) => a.altitude - b.altitude);\n\t\tif (sortedSpaces && sortedSpaces.length === this.aboveGroundFloors.length) {\n\t\t\tfor (const idx in this.aboveGroundFloors) {\n\t\t\t\tconst floor = this.aboveGroundFloors[idx];\n\t\t\t\tconst space = sortedSpaces[idx];\n\t\t\t\tthis.floorsAltitudesMap.set(floor.elevation, {\n\t\t\t\t\taltitude: space.altitude,\n\t\t\t\t\teffectiveHeight: space.height,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tget id() {\n\t\treturn this.#floorStack.id;\n\t}\n\n\tget name() {\n\t\treturn this.#floorStack.name;\n\t}\n\n\tget floors() {\n\t\treturn this.#floorStack.floors;\n\t}\n\n\tget floorStack() {\n\t\treturn this.#floorStack;\n\t}\n\n\tget facade() {\n\t\t// the floorstack must have a facade if we created a building for it\n\t\treturn this.#floorStack.facade!;\n\t}\n\n\tget isCurrentFloorStack() {\n\t\treturn this.id === this.#mapView.currentFloorStack.id;\n\t}\n\n\tget isIndoor() {\n\t\tconst state = this.#mapView.getState(this.facade);\n\n\t\treturn this.isCurrentFloorStack || (state?.visible === false && state?.opacity === 0);\n\t}\n\n\tget canSetFloor() {\n\t\treturn this.isIndoor || !this.excluded;\n\t}\n\n\t#maxElevation: number | undefined;\n\tget maxElevation() {\n\t\tif (this.#maxElevation == null) {\n\t\t\tthis.#maxElevation = Math.max(...this.#floorsByElevation.keys());\n\t\t}\n\n\t\treturn this.#maxElevation;\n\t}\n\n\t#minElevation: number | undefined;\n\tget minElevation() {\n\t\tif (this.#minElevation == null) {\n\t\t\tthis.#minElevation = Math.min(...this.#floorsByElevation.keys());\n\t\t}\n\n\t\treturn this.#minElevation;\n\t}\n\n\thas(f: Floor | FloorStack | Facade) {\n\t\tif (Floor.is(f)) {\n\t\t\treturn this.#floorsById.has(f.id);\n\t\t}\n\n\t\tif (FloorStack.is(f)) {\n\t\t\treturn f.id === this.#floorStack.id;\n\t\t}\n\n\t\tif (Facade.is(f)) {\n\t\t\treturn f.id === this.facade.id;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tgetFloorByElevation(elevation: number) {\n\t\treturn this.#floorsByElevation.get(elevation);\n\t}\n\n\tgetNearestFloorByElevation(targetElevation: number): Floor | undefined {\n\t\tconst exactMatch = this.getFloorByElevation(targetElevation);\n\t\tif (exactMatch) {\n\t\t\treturn exactMatch;\n\t\t}\n\n\t\tif (targetElevation >= 0) {\n\t\t\t// For positive elevations, return highest floor if target is above max\n\t\t\tif (targetElevation > this.maxElevation) {\n\t\t\t\treturn this.#floorsByElevationSorted[this.#floorsByElevationSorted.length - 1];\n\t\t\t}\n\n\t\t\t// Search backwards from the end\n\t\t\tfor (let i = this.#floorsByElevationSorted.length - 1; i >= 0; i--) {\n\t\t\t\tconst floor = this.#floorsByElevationSorted[i];\n\t\t\t\tif (floor.elevation <= targetElevation) {\n\t\t\t\t\treturn floor;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// For negative elevations (basements), return the lowest floor if target is below min\n\t\t\tif (targetElevation < this.minElevation) {\n\t\t\t\treturn this.#floorsByElevationSorted[0];\n\t\t\t}\n\n\t\t\t// Search forwards from the start\n\t\t\tfor (const floor of this.#floorsByElevationSorted) {\n\t\t\t\tif (floor.elevation >= targetElevation) {\n\t\t\t\t\treturn floor;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\tgetHighestFloor(): Floor {\n\t\treturn this.#floorsByElevationSorted[this.#floorsByElevationSorted.length - 1];\n\t}\n\n\tcancelAnimation() {\n\t\tif (this.#animationInProgress) {\n\t\t\tthis.#animationInProgress.animation.cancel();\n\t\t\tthis.#animationInProgress = undefined;\n\t\t}\n\t}\n\n\tasync animateFacade(\n\t\tnewState: TFacadeState,\n\t\toptions: DynamicFocusAnimationOptions = { duration: 150 },\n\t): Promise<TAnimateStateResult> {\n\t\tconst currentState = this.#animationInProgress?.state || this.#mapView.getState(this.facade);\n\t\tif (\n\t\t\t!currentState ||\n\t\t\t!newState ||\n\t\t\t(currentState?.opacity === newState.opacity && currentState?.visible === newState.visible)\n\t\t) {\n\t\t\t// nothing to do\n\t\t\treturn { result: 'completed' };\n\t\t}\n\n\t\tthis.cancelAnimation();\n\t\tconst { opacity, visible } = newState;\n\n\t\t// always set facade visible so it can be seen during animation\n\t\tthis.#mapView.updateState(this.facade, {\n\t\t\tvisible: true,\n\t\t});\n\n\t\tif (opacity !== undefined) {\n\t\t\tthis.#animationInProgress = {\n\t\t\t\tanimation: this.#mapView.animateState(\n\t\t\t\t\tthis.facade,\n\t\t\t\t\t{\n\t\t\t\t\t\topacity,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tduration: options.duration,\n\t\t\t\t\t},\n\t\t\t\t),\n\t\t\t\tstate: newState,\n\t\t\t};\n\t\t\tconst result = await this.#animationInProgress.animation;\n\n\t\t\tthis.#animationInProgress = undefined;\n\n\t\t\tif (result.result === 'cancelled') {\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\n\t\tif (visible === false) {\n\t\t\tthis.#mapView.updateState(this.facade, {\n\t\t\t\tvisible,\n\t\t\t});\n\t\t}\n\n\t\treturn { result: 'completed' };\n\t}\n\n\tdestroy() {\n\t\tthis.cancelAnimation();\n\t\t// Hide all floors except current floor\n\t\tthis.#floorStack.floors.forEach(floor => {\n\t\t\tthis.#mapView.updateState(floor, {\n\t\t\t\tvisible: floor.id === this.#mapView.currentFloor.id,\n\t\t\t});\n\t\t});\n\t\t// Show the facade if the current floor is not in this building\n\t\tif (!this.has(this.#mapView.currentFloor)) {\n\t\t\tthis.#mapView.updateState(this.facade, {\n\t\t\t\tvisible: true,\n\t\t\t\topacity: 1,\n\t\t\t});\n\t\t}\n\t}\n}\n", "import type { Facade, Floor, FloorStack, TFloorState } from '@mappedin/mappedin-js';\nimport type { Building } from './building';\nimport type {\n\tBuildingAnimation,\n\tBuildingFacadeState,\n\tBuildingFloorStackState,\n\tDynamicFocusMode,\n\tMultiFloorVisibilityState,\n\tZoomState,\n} from './types';\nimport type { Outdoors } from './outdoors';\n\n/**\n * Calculates the zoom state based on camera zoom level and thresholds.\n */\nexport function getZoomState(zoomLevel: number, indoorThreshold: number, outdoorThreshold: number): ZoomState {\n\tif (zoomLevel >= indoorThreshold) {\n\t\treturn 'in-range';\n\t}\n\tif (zoomLevel <= outdoorThreshold) {\n\t\treturn 'out-of-range';\n\t}\n\n\treturn 'transition';\n}\n\nexport function getFloorToShow(\n\ttarget: Building | Outdoors,\n\tmode: DynamicFocusMode,\n\televation: number,\n): Floor | undefined {\n\tif (target.__type === 'outdoors' && 'floor' in target) {\n\t\treturn target.floor;\n\t}\n\n\tconst building = target as Building;\n\tif (building.excluded) {\n\t\treturn building.activeFloor;\n\t}\n\n\tswitch (mode) {\n\t\tcase 'lock-elevation':\n\t\t\treturn building.getFloorByElevation(elevation);\n\t\tcase 'nearest-elevation':\n\t\t\treturn building.getNearestFloorByElevation(elevation);\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\t// if the building is already showing, don't switch to the default floor\n\treturn building.isIndoor ? building.activeFloor : building.defaultFloor;\n}\n\nexport function getFacadeState(facade: Facade, inFocus: boolean): BuildingFacadeState {\n\treturn {\n\t\tfacade,\n\t\tstate: {\n\t\t\ttype: 'facade',\n\t\t\tvisible: !inFocus,\n\t\t\topacity: inFocus ? 0 : 1,\n\t\t},\n\t};\n}\n\nexport function getSingleBuildingState(\n\tfloorStack: FloorStack,\n\tcurrentFloor: Floor,\n\tinFocus: boolean,\n): BuildingFloorStackState {\n\treturn {\n\t\toutdoorOpacity: 1,\n\t\tfloorStates: floorStack.floors.map(f => {\n\t\t\tconst visible = f.id === currentFloor.id && inFocus;\n\n\t\t\treturn {\n\t\t\t\tfloor: f,\n\t\t\t\tstate: {\n\t\t\t\t\ttype: 'floor',\n\t\t\t\t\tvisible: visible,\n\t\t\t\t\tgeometry: {\n\t\t\t\t\t\tvisible: visible,\n\t\t\t\t\t},\n\t\t\t\t\tlabels: {\n\t\t\t\t\t\tenabled: visible,\n\t\t\t\t\t},\n\t\t\t\t\tmarkers: {\n\t\t\t\t\t\tenabled: visible,\n\t\t\t\t\t},\n\t\t\t\t\tfootprint: {\n\t\t\t\t\t\tvisible: false,\n\t\t\t\t\t},\n\t\t\t\t\tocclusion: {\n\t\t\t\t\t\tenabled: false,\n\t\t\t\t\t},\n\t\t\t\t} as Required<TFloorState>,\n\t\t\t};\n\t\t}),\n\t};\n}\n\n/**\n * Calculates the outdoor opacity based on floor stack states and mode.\n */\nexport function getOutdoorOpacity(floorStackStates: BuildingFloorStackState[], mode: DynamicFocusMode): number {\n\tif (!mode.includes('lock-elevation')) {\n\t\treturn 1;\n\t}\n\n\tfor (const state of floorStackStates) {\n\t\tif (state.outdoorOpacity >= 0 && state.outdoorOpacity <= 1) {\n\t\t\treturn state.outdoorOpacity;\n\t\t}\n\t}\n\n\treturn 1;\n}\n\nexport function getSetFloorTargetFromZoomState(\n\tbuildings: Building[],\n\toutdoors: Outdoors,\n\tzoomState: ZoomState,\n): Building | Outdoors | undefined {\n\tswitch (zoomState) {\n\t\tcase 'in-range':\n\t\t\treturn buildings[0]?.canSetFloor ? buildings[0] : undefined;\n\t\tcase 'out-of-range':\n\t\t\treturn outdoors;\n\t\tcase 'transition':\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n}\n\n/**\n * Gets the building states for all buildings.\n */\nexport function getBuildingStates(\n\tbuildings: Building[],\n\tinViewSet: Set<string>,\n\tcurrentFloor: Floor,\n\tzoomState: ZoomState,\n\tmode: DynamicFocusMode,\n\televation: number,\n\tfloorIdsInNavigation: string[],\n\tfloorStackIdsInNavigation: string[],\n\tmultiFloorView: any,\n\tgetMultiFloorState: MultiFloorVisibilityState,\n\tdynamicBuildingInteriors: boolean,\n): Map<\n\tstring,\n\t{\n\t\tbuilding: Building;\n\t\tshowIndoor: boolean;\n\t\tfloorStackState: BuildingFloorStackState;\n\t\tfacadeState: BuildingFacadeState;\n\t\tinFocus: boolean;\n\t\tfloorToShow: Floor | undefined;\n\t}\n> {\n\tconst buildingStates = new Map();\n\n\tfor (const building of buildings) {\n\t\tconst inCameraView = inViewSet.has(building.id);\n\t\tconst showIndoor = shouldShowIndoor(\n\t\t\tbuilding,\n\t\t\tcurrentFloor,\n\t\t\tzoomState === 'in-range',\n\t\t\tinCameraView,\n\t\t\tmode,\n\t\t\televation,\n\t\t\tfloorStackIdsInNavigation.includes(building.id),\n\t\t\tdynamicBuildingInteriors,\n\t\t);\n\n\t\tconst floorToShow =\n\t\t\tcurrentFloor.floorStack.id === building.id ? building.activeFloor : getFloorToShow(building, mode, elevation);\n\n\t\tconst floorStackState = multiFloorView.enabled\n\t\t\t? getMultiFloorState(\n\t\t\t\t\tbuilding.floors,\n\t\t\t\t\tfloorToShow || building.activeFloor,\n\t\t\t\t\tmultiFloorView?.floorGap,\n\t\t\t\t\tfloorIdsInNavigation,\n\t\t\t\t\tbuilding.floorsAltitudesMap,\n\t\t\t )\n\t\t\t: getSingleBuildingState(building.floorStack, floorToShow || building.activeFloor, showIndoor);\n\n\t\tconst facadeState = getFacadeState(building.facade, showIndoor);\n\t\tbuildingStates.set(building.id, {\n\t\t\tbuilding,\n\t\t\tshowIndoor,\n\t\t\tfloorStackState,\n\t\t\tfacadeState,\n\t\t\tinFocus: inCameraView,\n\t\t\tfloorToShow,\n\t\t});\n\t}\n\n\treturn buildingStates;\n}\n\nexport function getBuildingAnimationType(building: Building, showIndoor: boolean): BuildingAnimation {\n\tif (building.excluded) {\n\t\treturn 'none';\n\t}\n\n\tif (showIndoor) {\n\t\treturn 'indoor';\n\t}\n\n\treturn 'outdoor';\n}\n\n/**\n * Determines if a building's indoor floors should be shown through a number of different state checks.\n */\nexport function shouldShowIndoor(\n\tbuilding: Building,\n\tcurrentFloor: Floor,\n\tinRange: boolean,\n\tinFocus: boolean,\n\tmode: DynamicFocusMode,\n\televation: number,\n\tinNavigation: boolean,\n\tdynamicBuildingInteriors: boolean,\n): boolean {\n\t// always show the current floor regardless of any other states\n\tif (building.id === currentFloor.floorStack.id) {\n\t\treturn true;\n\t}\n\n\t// if the building is excluded, we don't control the visibility, so don't show it\n\tif (building.excluded) {\n\t\treturn false;\n\t}\n\n\t// if it's not excluded, always show the navigation\n\tif (inNavigation === true) {\n\t\treturn true;\n\t}\n\n\t// Without dynamic building interiors, we only rely on whether the current floor is indoor or outdoor\n\tif (!dynamicBuildingInteriors) {\n\t\treturn currentFloor.floorStack.type !== 'Outdoor';\n\t}\n\n\t// the following cases rely on the camera being in range\n\tif (!inRange) {\n\t\treturn false;\n\t}\n\n\t// the following cases rely on the building being in focus\n\tif (!inFocus) {\n\t\treturn false;\n\t}\n\n\tswitch (mode) {\n\t\tcase 'lock-elevation':\n\t\t\treturn building.getFloorByElevation(elevation) != null;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\treturn true;\n}\n\nexport function shouldDeferSetFloor(\n\ttrackedCameraElevation: number,\n\tcurrentCameraElevation: number,\n\tuserInteracting: boolean,\n): boolean {\n\treturn trackedCameraElevation !== currentCameraElevation && !userInteracting;\n}\n", "import type { Facade, Floor, TFacadeState } from '@mappedin/mappedin-js';\nimport type { VisibilityState as BuildingFloorStackState } from '../../mappedin-js/src/api-geojson/multi-floor';\n\nexport type MultiFloorVisibilityState = (\n\tfloors: Floor[],\n\tcurrentFloor: Floor,\n\tfloorGap: number,\n\tfloorIdsInNavigation: Floor['id'][],\n\tfloorsVisualHeightMap?: Map<number, { altitude: number; effectiveHeight: number }>,\n) => BuildingFloorStackState;\n\nexport type DynamicFocusAnimationOptions = {\n\t/**\n\t * The duration of the animation in milliseconds.\n\t * @default 150\n\t */\n\tduration: number;\n};\n\n/**\n * Array of valid dynamic focus modes for runtime validation.\n */\nexport const DYNAMIC_FOCUS_MODES = ['default-floor', 'lock-elevation', 'nearest-elevation'] as const;\n\n/**\n * The mode which determines the indoor floor to reveal when the camera focuses on a facade.\n * - 'default-floor' - Show the default floor of the floor stack.\n * - 'lock-elevation' - Show the floor at the current elevation, if possible.\n * When a floor stack does not have a floor at the current elevation, no indoor floor will be shown.\n * - 'nearest-elevation' - Show the floor at the current elevation, if possible.\n * When a floor stack does not have a floor at the current elevation, show the indoor floor at the nearest lower elevation.\n */\nexport type DynamicFocusMode = (typeof DYNAMIC_FOCUS_MODES)[number];\n\n/**\n * State of the Dynamic Focus controller.\n */\nexport type DynamicFocusState = {\n\t/**\n\t * Whether to automatically focus on the outdoors when the camera moves in range.\n\t * @default true\n\t */\n\tautoFocus: boolean;\n\t/**\n\t * The zoom level at which the camera will fade out the facades and fade in the indoor floors.\n\t * @default 18\n\t */\n\tindoorZoomThreshold: number;\n\t/**\n\t * The zoom level at which the camera will fade in the facades and fade out the indoor floors.\n\t * @default 17\n\t */\n\toutdoorZoomThreshold: number;\n\t/**\n\t * Whether to set the floor to the outdoors when the camera moves in range.\n\t * @default true\n\t */\n\tsetFloorOnFocus: boolean;\n\t/**\n\t * Options for the animation when fading out the facade to reveal the interior.\n\t */\n\tindoorAnimationOptions: DynamicFocusAnimationOptions;\n\t/**\n\t * Options for the animation when fading in the facade to hide the interior.\n\t */\n\toutdoorAnimationOptions: DynamicFocusAnimationOptions;\n\t/**\n\t * The mode of the Dynamic Focus controller.\n\t * @default 'default-floor'\n\t */\n\tmode: DynamicFocusMode;\n\t/**\n\t * Whether to automatically adjust facade heights to align with floor boundaries in multi-floor buildings.\n\t * @default false\n\t */\n\tautoAdjustFacadeHeights: boolean;\n\t/**\n\t * Whether to automatically hide the indoors of buildings not in or near the camera's view.\n\t * @default true\n\t */\n\tdynamicBuildingInteriors: boolean;\n\t/**\n\t * Whether to preload the geometry of the initial floors in each building. Improves performance when rendering the building for the first time.\n\t * @default true\n\t */\n\tpreloadFloors: boolean;\n\n\t/**\n\t * @experimental\n\t * @internal\n\t * A custom function to override the default floor visibility state.\n\t * This is useful for customizing the floor visibility state for a specific building.\n\t */\n\tcustomMultiFloorVisibilityState?: MultiFloorVisibilityState;\n};\n\n/**\n * Internal events emitted for updating React state.\n */\nexport type InternalDynamicFocusEvents = {\n\t'state-change': undefined;\n};\n\n/**\n * Events emitted by the Dynamic Focus controller.\n */\nexport type DynamicFocusEvents = {\n\t/**\n\t * Emitted when the Dynamic Focus controller triggers a focus update either from a camera change or manually calling `focus()`.\n\t */\n\tfocus: {\n\t\tfacades: Facade[];\n\t};\n};\n\nexport type DynamicFocusEventPayload<EventName extends keyof DynamicFocusEvents> =\n\tDynamicFocusEvents[EventName] extends { data: null }\n\t\t? DynamicFocusEvents[EventName]['data']\n\t\t: DynamicFocusEvents[EventName];\n\nexport type BuildingFacadeState = {\n\tfacade: Facade;\n\tstate: TFacadeState;\n};\n\nexport type BuildingState = BuildingFloorStackState & {\n\tfacadeState: BuildingFacadeState;\n};\n\nexport type ZoomState = 'in-range' | 'out-of-range' | 'transition';\nexport type ViewState = 'indoor' | 'outdoor' | 'transition';\n\nexport type BuildingAnimation = 'indoor' | 'outdoor' | 'none';\n\nexport type { BuildingFloorStackState };\n", "import { Floor, FloorStack } from '@mappedin/mappedin-js';\nimport { clampWithWarning } from '@packages/internal/common/math-utils';\nimport Logger from '@packages/internal/common/Mappedin.Logger';\n\n/**\n * Validates that a floor belongs to the specified floor stack.\n */\nexport function validateFloorForStack(floor: Floor, floorStack: FloorStack): boolean {\n\tif (!Floor.is(floor) || floor?.floorStack == null || !FloorStack.is(floorStack)) {\n\t\treturn false;\n\t}\n\n\tif (floor.floorStack.id !== floorStack.id) {\n\t\tLogger.warn(`Floor (${floor.id}) does not belong to floor stack (${floorStack.id}).`);\n\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n/**\n * Validates and clamps zoom threshold values.\n */\nexport function validateZoomThreshold(value: number, min: number, max: number, name: string): number {\n\treturn clampWithWarning(value, min, max, `${name} must be between ${min} and ${max}.`);\n}\n", "/* eslint-disable no-console*/\nexport const MI_DEBUG_KEY = 'mi-debug';\nexport const MI_ERROR_LABEL = '[MappedinJS]';\n\nexport enum E_SDK_LOG_LEVEL {\n\tLOG,\n\tWARN,\n\tERROR,\n\tSILENT,\n}\n\nexport function createLogger(name = '', { prefix = MI_ERROR_LABEL } = {}) {\n\tconst label = `${prefix}${name ? `-${name}` : ''}`;\n\n\tconst rnDebug = (type: 'log' | 'warn' | 'error', args: any[]) => {\n\t\tif (typeof window !== 'undefined' && (window as any).rnDebug) {\n\t\t\tconst processed = args.map(arg => {\n\t\t\t\tif (arg instanceof Error && arg.stack) {\n\t\t\t\t\treturn `${arg.message}\\n${arg.stack}`;\n\t\t\t\t}\n\n\t\t\t\treturn arg;\n\t\t\t});\n\t\t\t(window as any).rnDebug(`${name} ${type}: ${processed.join(' ')}`);\n\t\t}\n\t};\n\n\treturn {\n\t\tlogState: process.env.NODE_ENV === 'test' ? E_SDK_LOG_LEVEL.SILENT : E_SDK_LOG_LEVEL.LOG,\n\n\t\tlog(...args: any[]) {\n\t\t\tif (this.logState <= E_SDK_LOG_LEVEL.LOG) {\n\t\t\t\tconsole.log(label, ...args);\n\t\t\t\trnDebug('log', args);\n\t\t\t}\n\t\t},\n\n\t\twarn(...args: any[]) {\n\t\t\tif (this.logState <= E_SDK_LOG_LEVEL.WARN) {\n\t\t\t\tconsole.warn(label, ...args);\n\t\t\t\trnDebug('warn', args);\n\t\t\t}\n\t\t},\n\n\t\terror(...args: any[]) {\n\t\t\tif (this.logState <= E_SDK_LOG_LEVEL.ERROR) {\n\t\t\t\tconsole.error(label, ...args);\n\n\t\t\t\trnDebug('error', args);\n\t\t\t}\n\t\t},\n\n\t\t// It's a bit tricky to prepend [MappedinJs] to assert and time because of how the output is structured in the console, so it is left out for simplicity\n\t\tassert(...args: any[]) {\n\t\t\tconsole.assert(...args);\n\t\t},\n\n\t\ttime(label: string) {\n\t\t\tconsole.time(label);\n\t\t},\n\n\t\ttimeEnd(label: string) {\n\t\t\tconsole.timeEnd(label);\n\t\t},\n\t\tsetLevel(level: E_SDK_LOG_LEVEL) {\n\t\t\tif (E_SDK_LOG_LEVEL.LOG <= level && level <= E_SDK_LOG_LEVEL.SILENT) {\n\t\t\t\tthis.logState = level;\n\t\t\t}\n\t\t},\n\t};\n}\n\nconst Logger = createLogger();\nexport function setLoggerLevel(level: E_SDK_LOG_LEVEL) {\n\tif (E_SDK_LOG_LEVEL.LOG <= level && level <= E_SDK_LOG_LEVEL.SILENT) {\n\t\tLogger.logState = level;\n\t}\n}\n\nexport default Logger;\n", "import Logger from './Mappedin.Logger';\n\n/**\n * Clamp a number between lower and upper bounds with a warning\n */\nexport function clampWithWarning(x: number, lower: number, upper: number, warning: string) {\n\tif (x < lower || x > upper) {\n\t\tLogger.warn(warning);\n\t}\n\n\treturn Math.min(upper, Math.max(lower, x));\n}\n", "import { createLogger } from '../../packages/common/Mappedin.Logger';\n\nexport const Logger = createLogger('', { prefix: '[DynamicFocus]' });\n", "import type { FloorStack, MapView } from '@mappedin/mappedin-js';\nimport { Logger } from './logger';\nimport type { Building } from './building';\n\nexport class Outdoors {\n\t__type = 'outdoors';\n\t#floorStack: FloorStack;\n\t#mapView: MapView;\n\n\tconstructor(floorStack: FloorStack, mapView: MapView) {\n\t\tthis.#floorStack = floorStack;\n\t\tthis.#mapView = mapView;\n\t}\n\n\tget id() {\n\t\treturn this.#floorStack.id;\n\t}\n\n\tget floorStack() {\n\t\treturn this.#floorStack;\n\t}\n\n\tget floor() {\n\t\t// outdoors should only have 1 floor\n\t\treturn this.#floorStack.defaultFloor;\n\t}\n\n\tmatchesFloorStack(floorStack: FloorStack | string) {\n\t\treturn floorStack === this.#floorStack || floorStack === this.#floorStack.id;\n\t}\n\n\t#setVisible(visible: boolean) {\n\t\tfor (const floor of this.#floorStack.floors) {\n\t\t\tthis.#mapView.updateState(floor, {\n\t\t\t\tvisible,\n\t\t\t});\n\t\t}\n\t}\n\n\tshow() {\n\t\tthis.#setVisible(true);\n\t}\n\n\thide() {\n\t\tthis.#setVisible(false);\n\t}\n\n\tdestroy() {\n\t\tif (!this.matchesFloorStack(this.#mapView.currentFloorStack)) {\n\t\t\tthis.hide();\n\t\t}\n\t}\n}\n\nexport function getOutdoorFloorStack(floorStacks: FloorStack[], buildingsSet: Map<string, Building>): FloorStack {\n\tconst outdoorFloorStack = floorStacks.find(floorStack => floorStack.type?.toLowerCase() === 'outdoor');\n\n\tif (outdoorFloorStack) {\n\t\treturn outdoorFloorStack;\n\t}\n\n\t// If no outdoor type found, find the first floor stack that does not have a facade or is already in the buildings set\n\tconst likelyOutdoorFloorStack = floorStacks.find(\n\t\tfloorStack => floorStack.facade == null && !buildingsSet.has(floorStack.id),\n\t);\n\n\tif (likelyOutdoorFloorStack) {\n\t\treturn likelyOutdoorFloorStack;\n\t}\n\n\tLogger.warn('No good candidate for the outdoor floor stack was found. Using the first floor stack.');\n\n\treturn floorStacks[0];\n}\n", "import { getMultiFloorState } from '@mappedin/mappedin-js';\nimport type { RequiredDeep } from 'type-fest';\nimport type { DynamicFocusState } from './types';\n\nexport const DEFAULT_STATE: RequiredDeep<DynamicFocusState> = {\n\tindoorZoomThreshold: 18,\n\toutdoorZoomThreshold: 17,\n\tsetFloorOnFocus: true,\n\tautoFocus: false,\n\tindoorAnimationOptions: {\n\t\tduration: 150,\n\t},\n\toutdoorAnimationOptions: {\n\t\tduration: 150,\n\t},\n\tautoAdjustFacadeHeights: false,\n\tmode: 'default-floor',\n\tpreloadFloors: true,\n\tcustomMultiFloorVisibilityState: getMultiFloorState,\n\tdynamicBuildingInteriors: true,\n};\n"],
5
- "mappings": "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",
6
- "names": ["Floor", "getMultiFloorState", "getMultiFloorState", "Floor", "FloorStack", "label", "Floor", "FloorStack", "Logger", "Logger", "Logger", "Floor", "getMultiFloorState"]
7
- }