import * as i0 from '@angular/core';
import { inject, Injectable, Component, ChangeDetectionStrategy, Directive, Injector, Optional, SkipSelf, output, viewChild, ElementRef, input, signal, effect, computed, NgModule, makeEnvironmentProviders } from '@angular/core';
import { asObservable, cleanup, filterMaybe, onTrueToFalse, SubscriptionObject, distinctUntilMapHasDifferentKeys } from '@dereekb/rxjs';
import { distinctUntilChanged, switchMap, map, combineLatestWith, shareReplay, NEVER, defaultIfEmpty, tap, EMPTY, interval, of, first, combineLatest, filter, startWith, throttleTime, Subject, merge, delay } from 'rxjs';
import { latLngPoint, LAT_LONG_10M_PRECISION, latLngPointFunction, roundNumberToStepFunction, latLngBoundFunction, latLngBoundFromInput, filterUndefinedValues, diffLatLngBoundPoints, latLngBoundCenterPoint, addLatLngPoints, isSameLatLngPoint, isSameVector, vectorMinimumSizeResizeFunction, isSameLatLngBound, isDefaultLatLngPoint, swMostLatLngPoint, neMostLatLngPoint, latLngBoundWrapsMap, isWithinLatLngBoundFunction, overlapsLatLngBoundFunction, isNotFalse, DestroyFunctionObject, getValueFromGetter, pushItemOrArrayItemsIntoArray, spaceSeparatedCssClasses } from '@dereekb/util';
import { ComponentStore } from '@ngrx/component-store';
import * as MapboxGl from 'mapbox-gl';
import { bounds } from '@placemarkio/geo-viewport';
import { DbxInjectionArrayComponent, DbxInjectionComponent, AbstractSubscriptionDirective } from '@dereekb/dbx-core';
import { toSignal, toObservable } from '@angular/core/rxjs-interop';
import { MapService, MapComponent, MAP_COMPONENT_INITIALIZATION_OPTIONS, MarkerComponent, provideMapboxGL } from 'ngx-mapbox-gl';
import { DbxResizedDirective, DbxColorDirective, disableRightClickInCdkBackdrop, DbxAnchorComponent } from '@dereekb/dbx-web';
import { MatDrawerContainer, MatDrawer, MatDrawerContent } from '@angular/material/sidenav';
import { NgClass, NgStyle } from '@angular/common';
import { MatIconButton } from '@angular/material/button';
import * as i1 from '@angular/material/icon';
import { MatIconModule } from '@angular/material/icon';
import { MatMenuTrigger } from '@angular/material/menu';

class DbxMapboxConfig {
    defaultStyle;
    defaultZoom;
    defaultCenter;
    defaultStoreRefreshPeriod;
}
const DEFAULT_MAPBOX_STYLE = 'mapbox://styles/mapbox/streets-v12';
const DEFAULT_MAPBOX_CENTER = [30.2690138665, -97.7408297965];
const DEFAULT_MAPBOX_ZOOM = 8;
const DEFAULT_MAPBOX_MAP_STORE_TIMER_REFRESH_PERIOD = 200;
class DbxMapboxService {
    _config = inject(DbxMapboxConfig, { optional: true }) ?? {};
    get defaultStyle() {
        return this._config.defaultStyle ?? DEFAULT_MAPBOX_STYLE;
    }
    get defaultZoom() {
        return this._config.defaultZoom ?? DEFAULT_MAPBOX_ZOOM;
    }
    get defaultCenter() {
        return this._config.defaultCenter ?? DEFAULT_MAPBOX_CENTER;
    }
    get mapboxMapStoreTimerRefreshPeriod() {
        return this._config.defaultStoreRefreshPeriod ?? DEFAULT_MAPBOX_MAP_STORE_TIMER_REFRESH_PERIOD;
    }
    initializationOptions() {
        return {
            style: this.defaultStyle,
            zoom: this.defaultZoom,
            center: latLngPoint(this.defaultCenter)
        };
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxService });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxService, decorators: [{
            type: Injectable
        }] });

function mapboxViewportBoundFunction(config) {
    const { mapCanvasSize, tileSize = 512 } = config;
    const dimensions = [mapCanvasSize.x, mapCanvasSize.y];
    return ({ center, zoom }) => {
        const boundingBox = bounds([center.lng, center.lat], zoom, dimensions, tileSize);
        const [swLng, swLat, neLng, neLat] = boundingBox;
        const result = {
            sw: { lat: swLat, lng: swLng },
            ne: { lat: neLat, lng: neLng }
        };
        return result;
    };
}

/**
 * Filters the input objects based on their center and zoom values.
 *
 * This function caches the bounds computations for each of the input values.
 *
 * @param config
 * @returns
 */
function filterByMapboxViewportBound(config) {
    const { boundDecisionObs: inputBoundDecisionObs, boundFunctionObs: inputBoundFunctionObs, defaultZoom: inputDefaultZoom = 17, readValue, zoomRounding, precision = LAT_LONG_10M_PRECISION } = config;
    const _latLngPoint = latLngPointFunction({ wrap: false, validate: false, precision });
    const _roundZoom = roundNumberToStepFunction(zoomRounding || { step: 0.5, round: 'floor' });
    const boundDecisionObs = asObservable(inputBoundDecisionObs);
    const boundFunctionObs = asObservable(inputBoundFunctionObs);
    return (input) => {
        return boundFunctionObs.pipe(distinctUntilChanged(), switchMap((viewportBoundFunction) => {
            const cache = new Map();
            return input.pipe(map((values) => {
                return values.map((value) => {
                    const item = readValue(value);
                    const centerLatLng = _latLngPoint(item.center);
                    const zoomStep = _roundZoom(item.zoom || inputDefaultZoom);
                    const cacheKey = `${zoomStep}_${centerLatLng.lat}_${centerLatLng.lng}`;
                    const cachedValue = cache.get(cacheKey);
                    let bound;
                    if (!cachedValue) {
                        bound = viewportBoundFunction({ center: centerLatLng, zoom: zoomStep });
                        cache.set(cacheKey, bound);
                    }
                    else {
                        bound = cachedValue;
                    }
                    return {
                        value,
                        bound
                    };
                });
            }), combineLatestWith(boundDecisionObs), map(([items, boundFunction]) => {
                const valuesInBounds = [];
                items.forEach((item) => {
                    if (boundFunction(item.bound)) {
                        valuesInBounds.push(item.value);
                    }
                });
                return valuesInBounds;
            }));
        }), shareReplay(1));
    };
}

/**
 * Store used for retrieving information.
 */
class DbxMapboxMapStore extends ComponentStore {
    dbxMapboxService = inject(DbxMapboxService);
    safeLatLngPoint = latLngPointFunction({ wrap: true });
    latLngPoint = latLngPointFunction({ wrap: false, validate: false });
    latLngBound = latLngBoundFunction({ pointFunction: this.latLngPoint });
    constructor() {
        super({
            lifecycleState: 'init',
            moveState: 'init',
            zoomState: 'init',
            rotateState: 'init',
            retainContent: true,
            useVirtualBound: true,
            boundRefreshSettings: {
                throttle: 300,
                refreshType: 'always'
            }
        });
    }
    // MARK: Effects
    setMapService = this.effect((input) => {
        return input.pipe(switchMap((service) => {
            this._setMapService(service);
            if (!service) {
                return NEVER;
            }
            else {
                return service.mapLoaded$.pipe(defaultIfEmpty(undefined), map(() => {
                    this._setLifecycleState('idle');
                    this._setMoveState('idle');
                    this._setZoomState('idle');
                    this._setRotateState('idle');
                    const map = service.mapInstance;
                    const listenerPairs = [];
                    function addListener(type, listener) {
                        map.on(type, listener);
                        listenerPairs.push({ type, listener });
                    }
                    addListener('idle', () => this._setLifecycleState('idle'));
                    addListener('render', () => this._setLifecycleState('render'));
                    addListener('error', (x) => {
                        this._setError(x.error);
                    });
                    addListener('movestart', () => this._setMoveState('moving'));
                    addListener('moveend', () => this._setMoveState('idle'));
                    addListener('zoomstart', () => this._setZoomState('zooming'));
                    addListener('zoomend', () => this._setZoomState('idle'));
                    addListener('rotatestart', () => this._setRotateState('rotating'));
                    addListener('rotateend', () => this._setRotateState('idle'));
                    addListener('click', (x) => this._setClickEvent(x));
                    addListener('dblclick', (x) => this._setDoubleClickEvent(x));
                    addListener('contextmenu', (x) => this._setRightClickEvent(x));
                    const refreshForResize = () => {
                        const { clientWidth: x, clientHeight: y } = map.getCanvas();
                        this._setMapCanvasSize({ x, y });
                    };
                    addListener('resize', refreshForResize);
                    refreshForResize();
                    const subs = [];
                    return {
                        service,
                        listenerPairs,
                        subs
                    };
                }));
            }
        }), cleanup(({ service, listenerPairs, subs }) => {
            const map = service.mapInstance;
            if (map) {
                listenerPairs.forEach((x) => {
                    map.off(x.type, x.listener);
                });
            }
            subs.forEach((sub) => sub.unsubscribe());
        }));
    });
    setStyle = this.effect((input) => {
        return input.pipe(switchMap((style) => {
            return this.mapInstance$.pipe(tap((map) => {
                if (typeof style === 'string') {
                    map.setStyle(style);
                }
                else {
                    map.setStyle(style.style, style.options);
                }
            }));
        }));
    });
    setCenter = this.effect((input) => {
        return input.pipe(switchMap((center) => {
            const centerPoint = this.safeLatLngPoint(center);
            return this.mapInstance$.pipe(tap((map) => map.setCenter(centerPoint)));
        }));
    });
    setZoom = this.effect((input) => {
        return input.pipe(switchMap((zoom) => {
            return this.mapInstance$.pipe(tap((map) => map.setZoom(zoom)));
        }));
    });
    setZoomRange = this.effect((input) => {
        return input.pipe(switchMap((zoomRange) => {
            return this.mapInstance$.pipe(tap((map) => {
                map.setMinZoom(zoomRange.min || null);
                map.setMaxZoom(zoomRange.max || null);
            }));
        }));
    });
    setMinZoom = this.effect((input) => {
        return input.pipe(switchMap((zoom) => {
            return this.mapInstance$.pipe(tap((map) => map.setMinZoom(zoom)));
        }));
    });
    setMaxZoom = this.effect((input) => {
        return input.pipe(switchMap((zoom) => {
            return this.mapInstance$.pipe(tap((map) => map.setMaxZoom(zoom)));
        }));
    });
    setKeyboardDisabled = this.effect((input) => {
        return input.pipe(switchMap((disabled) => {
            return this.mapInstance$.pipe(tap((map) => {
                if (disabled === false) {
                    map.keyboard.enable();
                }
                else {
                    map.keyboard.disable();
                }
            }));
        }));
    });
    setDragRotateDisabled = this.effect((input) => {
        return input.pipe(switchMap((disabled) => {
            return this.mapInstance$.pipe(tap((map) => {
                if (disabled === false) {
                    map.dragRotate.enable();
                }
                else {
                    map.dragRotate.disable();
                }
            }));
        }));
    });
    setDragPanDisabled = this.effect((input) => {
        return input.pipe(switchMap((disabled) => {
            return this.mapInstance$.pipe(tap((map) => {
                if (disabled === false) {
                    map.dragPan.enable();
                }
                else {
                    map.dragPan.disable();
                }
            }));
        }));
    });
    setZoomDisabled = this.effect((input) => {
        return input.pipe(switchMap((disabled) => {
            return this.mapInstance$.pipe(tap((map) => {
                if (disabled === false) {
                    map.scrollZoom.enable();
                    map.doubleClickZoom.enable();
                }
                else {
                    map.scrollZoom.disable();
                    map.doubleClickZoom.disable();
                }
            }));
        }));
    });
    setPitch = this.effect((input) => {
        return input.pipe(switchMap((pitch) => {
            return this.mapInstance$.pipe(tap((map) => map.setPitch(pitch)));
        }));
    });
    setMinPitch = this.effect((input) => {
        return input.pipe(switchMap((pitch) => {
            return this.mapInstance$.pipe(tap((map) => map.setMinPitch(pitch)));
        }));
    });
    setMaxPitch = this.effect((input) => {
        return input.pipe(switchMap((pitch) => {
            return this.mapInstance$.pipe(tap((map) => map.setMaxPitch(pitch)));
        }));
    });
    setBearing = this.effect((input) => {
        return input.pipe(switchMap((bearing) => {
            return this.mapInstance$.pipe(tap((map) => map.setBearing(bearing)));
        }));
    });
    rotateTo = this.effect((input) => {
        return input.pipe(switchMap((rotateInput) => {
            const rotate = typeof rotateInput === 'number' ? { bearing: rotateInput } : rotateInput;
            return this.mapInstance$.pipe(tap((map) => map.rotateTo(rotate.bearing, rotate.options, rotate?.eventData)));
        }));
    });
    resetNorth = this.effect((input) => {
        return input.pipe(switchMap((reset) => {
            return this.mapInstance$.pipe(tap((map) => map.resetNorth(reset?.options, reset?.eventData)));
        }));
    });
    resetNorthPitch = this.effect((input) => {
        return input.pipe(switchMap((reset) => {
            return this.mapInstance$.pipe(tap((map) => map.resetNorthPitch(reset?.options, reset?.eventData)));
        }));
    });
    snapToNorth = this.effect((input) => {
        return input.pipe(switchMap((snap) => {
            return this.mapInstance$.pipe(tap((map) => map.snapToNorth(snap?.options, snap?.eventData)));
        }));
    });
    fitPositions = this.effect((input) => {
        return input.pipe(switchMap((x) => {
            const boundFromInput = latLngBoundFromInput(x.positions);
            if (boundFromInput) {
                const bound = this.latLngBound(boundFromInput);
                return this.mapInstance$.pipe(tap((map) => map.fitBounds(new MapboxGl.LngLatBounds(bound.sw, bound.ne), x.options, x.eventData)));
            }
            else {
                return EMPTY;
            }
        }));
    });
    fitBounds = this.effect((input) => {
        return input.pipe(switchMap((x) => {
            const bound = this.latLngBound(x.bounds);
            return this.mapInstance$.pipe(tap((map) => map.fitBounds(new MapboxGl.LngLatBounds(bound.sw, bound.ne), x.options, x.eventData)));
        }));
    });
    jumpTo = this.effect((input) => {
        return input.pipe(switchMap((x) => {
            const inputCenter = x.center ?? x.to?.center;
            const center = inputCenter ? this.safeLatLngPoint(inputCenter) : undefined;
            return this.mapInstance$.pipe(tap((map) => map.jumpTo(filterUndefinedValues({ ...x.to, center }), x.eventData)));
        }));
    });
    easeTo = this.effect((input) => {
        return input.pipe(switchMap((x) => {
            const inputCenter = x.center ?? x.to?.center;
            const center = inputCenter ? this.safeLatLngPoint(inputCenter) : undefined;
            return this.mapInstance$.pipe(tap((map) => map.easeTo(filterUndefinedValues({ ...x.to, center }), x.eventData)));
        }));
    });
    flyTo = this.effect((input) => {
        return input.pipe(switchMap((x) => {
            const inputCenter = x.center ?? x.to?.center;
            const center = inputCenter ? this.safeLatLngPoint(inputCenter) : undefined;
            return this.mapInstance$.pipe(tap((map) => map.flyTo(filterUndefinedValues({ ...x.to, center }), x.eventData)));
        }));
    });
    resetPitchAndBearing = this.effect((input) => {
        return input.pipe(switchMap(() => {
            return this.mapInstance$.pipe(tap((map) => {
                map.setPitch(0);
                map.setBearing(0);
            }));
        }));
    });
    // MARK: Accessors
    get timerRefreshPeriod() {
        return this.dbxMapboxService.mapboxMapStoreTimerRefreshPeriod;
    }
    movingTimer(period = this.timerRefreshPeriod) {
        return this.moveState$.pipe(switchMap((x) => {
            if (x === 'moving') {
                return interval(period);
            }
            else {
                return of(0);
            }
        }), shareReplay(1));
    }
    lifecycleRenderTimer(period = this.timerRefreshPeriod) {
        return this.lifecycleState$.pipe(switchMap((x) => {
            if (x === 'render') {
                return interval(period);
            }
            else {
                return of(0);
            }
        }), shareReplay(1));
    }
    atNextIdle() {
        return this.moveState$.pipe(map((x) => x === 'idle'), first());
    }
    calculateNextCenterWithOffset(inputOffset) {
        const offset = this.latLngPoint(inputOffset);
        return this.atNextIdle().pipe(switchMap(() => this.center$.pipe(first(), map((center) => {
            const newCenter = {
                lat: offset.lat + center.lat,
                lng: offset.lng + center.lng
            };
            return newCenter;
        }))));
    }
    calculateNextCenterOffsetWithScreenMarginChange(sizing) {
        // TODO: Consider calculating this using the viewport() function from @placemarkio/geo-viewport
        return this.atNextIdle().pipe(switchMap(() => this.bound$.pipe(first(), map((bounds) => {
            const diff = diffLatLngBoundPoints(bounds, true);
            const center = latLngBoundCenterPoint(bounds);
            const offsetWidth = sizing.leftMargin + sizing.rightMargin; // 300 + 0
            const newWidth = sizing.fullWidth - offsetWidth; // 1000 - 300 - 0
            const newWidthRatio = newWidth / sizing.fullWidth; // 700 / 1000
            const newCenterLongitudeWidth = diff.lng * newWidthRatio; // 70% offset
            const effectiveOffset = {
                lat: 0,
                lng: newCenterLongitudeWidth / 2
            };
            const newCenter = addLatLngPoints(bounds.sw, effectiveOffset);
            newCenter.lat = center.lat; // retain center position
            // console.log({ sizing, bounds, effectiveOffset, newWidth, offsetWidth, diff, center, newCenter });
            return newCenter;
        }))));
    }
    filterByViewportBound(input) {
        const config = typeof input === 'function' ? { readValue: input } : input;
        return filterByMapboxViewportBound({
            ...config,
            boundFunctionObs: this.viewportBoundFunction$,
            boundDecisionObs: this.overlapsBoundFunction$
        });
    }
    currentMapService$ = this.state$.pipe(map((x) => x.mapService), distinctUntilChanged(), shareReplay(1));
    mapService$ = this.currentMapService$.pipe(filterMaybe());
    currentMapInstance$ = this.currentMapService$.pipe(switchMap((currentMapService) => {
        if (currentMapService) {
            return currentMapService.mapLoaded$.pipe(defaultIfEmpty(undefined), map(() => currentMapService.mapInstance));
        }
        else {
            return of(undefined);
        }
    }), distinctUntilChanged(), shareReplay(1));
    mapInstance$ = this.currentMapInstance$.pipe(filterMaybe());
    boundRefreshSettings$ = this.state$.pipe(map((x) => x.boundRefreshSettings), shareReplay(1));
    moveState$ = this.state$.pipe(map((x) => x.moveState), distinctUntilChanged(), shareReplay(1));
    lifecycleState$ = this.state$.pipe(map((x) => x.lifecycleState), distinctUntilChanged(), shareReplay(1));
    zoomState$ = this.state$.pipe(map((x) => x.zoomState), distinctUntilChanged(), shareReplay(1));
    rotateState$ = this.state$.pipe(map((x) => x.rotateState), distinctUntilChanged(), shareReplay(1));
    isInitialized$ = this.currentMapInstance$.pipe(switchMap((x) => {
        if (!x) {
            return of(false);
        }
        else {
            return combineLatest([this.moveState$.pipe(map((x) => x === 'idle')), this.lifecycleState$.pipe(map((x) => x === 'idle'))]).pipe(filter(([m, l]) => m && l), first(), map(() => true));
        }
    }), shareReplay(1));
    whenInitialized$ = this.isInitialized$.pipe(filter((x) => true), shareReplay(1));
    isRendering$ = this.whenInitialized$.pipe(switchMap(() => this.lifecycleState$.pipe(map((x) => x === 'render'), distinctUntilChanged(), shareReplay(1))));
    isMoving$ = this.whenInitialized$.pipe(switchMap(() => this.moveState$.pipe(map((x) => x === 'moving'), distinctUntilChanged(), shareReplay(1))));
    isZooming$ = this.whenInitialized$.pipe(switchMap(() => this.zoomState$.pipe(map((x) => x === 'zooming'), distinctUntilChanged(), shareReplay(1))));
    isRotating$ = this.whenInitialized$.pipe(switchMap(() => this.rotateState$.pipe(map((x) => x === 'rotating'), distinctUntilChanged(), shareReplay(1))));
    _movingTimer = this.movingTimer();
    _renderingTimer = this.lifecycleRenderTimer();
    centerNow$ = this.whenInitialized$.pipe(switchMap(() => this.mapInstance$.pipe(switchMap((x) => this._movingTimer.pipe(map(() => this.latLngPoint(x.getCenter())))), shareReplay(1))), shareReplay(1));
    center$ = this.whenInitialized$.pipe(switchMap(() => {
        return this.isMoving$.pipe(onTrueToFalse(), startWith(undefined), switchMap(() => this.centerNow$.pipe(first())), distinctUntilChanged(isSameLatLngPoint), shareReplay(1));
    }), shareReplay(1));
    minimumVirtualViewportSize$ = this.state$.pipe(map((x) => x.minimumVirtualViewportSize), distinctUntilChanged(isSameVector), shareReplay(1));
    currentMapCanvasSize$ = this.state$.pipe(map((x) => x.mapCanvasSize), distinctUntilChanged(isSameVector), shareReplay(1));
    /**
     * The map canvas size with consideration to the virtual viewport size.
     */
    mapCanvasSize$ = this.currentMapCanvasSize$.pipe(filterMaybe());
    minimumMapCanvasSize(minVector) {
        const resizeFn = vectorMinimumSizeResizeFunction(minVector);
        return this.mapCanvasSize$.pipe(map((x) => resizeFn(x)), distinctUntilChanged(isSameVector), shareReplay(1));
    }
    /**
     * The map canvas size with consideration to the virtual viewport size.
     */
    virtualMapCanvasSize$ = this.minimumVirtualViewportSize$.pipe(switchMap((minimumVirtualViewportSize) => {
        if (minimumVirtualViewportSize) {
            return this.minimumMapCanvasSize(minimumVirtualViewportSize);
        }
        else {
            return this.mapCanvasSize$;
        }
    }), distinctUntilChanged(isSameVector), shareReplay(1));
    rawViewportBoundFunction$ = this.mapCanvasSize$.pipe(map((mapCanvasSize) => mapboxViewportBoundFunction({ mapCanvasSize })), shareReplay(1));
    /**
     * Creates a MapboxViewportBoundFunction observable that returns the minimum viewport size.
     *
     * @param minVector
     * @returns
     */
    viewportBoundFunctionWithMinimumSize(minVector) {
        const resizeFn = vectorMinimumSizeResizeFunction(minVector);
        return this.mapCanvasSize$.pipe(map((x) => resizeFn(x)), distinctUntilChanged(isSameVector), map((mapCanvasSize) => mapboxViewportBoundFunction({ mapCanvasSize })), shareReplay(1));
    }
    viewportBoundFunction$ = this.minimumVirtualViewportSize$.pipe(switchMap((minimumVirtualViewportSize) => {
        if (minimumVirtualViewportSize) {
            return this.viewportBoundFunctionWithMinimumSize(minimumVirtualViewportSize);
        }
        else {
            return this.rawViewportBoundFunction$;
        }
    }), shareReplay(1));
    virtualBound$ = this.viewportBoundFunction$.pipe(switchMap((fn) => {
        return this.boundRefreshSettings$.pipe(switchMap((settings) => {
            const { throttle: throttleMs, refreshType } = settings;
            let obs;
            switch (refreshType) {
                case 'always':
                    obs = combineLatest([this.centerNow$, this.zoomNow$]);
                    break;
                case 'when_not_rendering':
                case 'only_after_render_finishes':
                    obs = this.bound$.pipe(switchMap(() => combineLatest([this.centerNow$, this.zoomNow$]))); // refresh whenever the bound refreshes
                    break;
            }
            return obs.pipe(throttleTime(throttleMs, undefined, { leading: true, trailing: true }), map(([center, zoom]) => fn({
                center,
                zoom
            })));
        }));
    }), distinctUntilChanged(isSameLatLngBound), shareReplay(1));
    margin$ = this.state$.pipe(map((x) => x.margin), distinctUntilChanged((a, b) => a != null && b != null && a.fullWidth === b.fullWidth && a.leftMargin === b.leftMargin && a.rightMargin === b.rightMargin), shareReplay(1));
    reverseMargin$ = this.margin$.pipe(map((x) => {
        if (x) {
            return { leftMargin: -x.leftMargin, rightMargin: -x.rightMargin, fullWidth: x.fullWidth };
        }
        else {
            return x;
        }
    }));
    centerGivenMargin$ = this.whenInitialized$.pipe(switchMap(() => {
        return this.reverseMargin$.pipe(switchMap((x) => {
            if (x) {
                return this.center$.pipe(switchMap((_) => this.calculateNextCenterOffsetWithScreenMarginChange(x)));
            }
            else {
                return this.isMoving$.pipe(filter((x) => !x), switchMap(() => this.center$));
            }
        }));
    }), shareReplay(1));
    rawBoundNow$ = this.whenInitialized$.pipe(switchMap(() => this.mapInstance$.pipe(switchMap((x) => this._renderingTimer.pipe(map(() => {
        const bound = x.getBounds();
        let result = null;
        if (bound != null) {
            const boundSw = bound.getSouthWest();
            const boundNe = bound.getNorthEast();
            const sw = isDefaultLatLngPoint(boundSw) ? swMostLatLngPoint() : { lat: boundSw.lat, lng: boundSw.lng };
            const ne = isDefaultLatLngPoint(boundNe) ? neMostLatLngPoint() : { lat: boundNe.lat, lng: boundNe.lng };
            result = this.latLngBound(sw, ne);
        }
        return result;
    }), filterMaybe())))), distinctUntilChanged(isSameLatLngBound), shareReplay(1));
    rawBound$ = this.whenInitialized$.pipe(switchMap(() => {
        return this.boundRefreshSettings$.pipe(switchMap((settings) => {
            const { throttle: throttleMs, refreshType } = settings;
            let obs;
            switch (refreshType) {
                case 'always':
                    obs = this.rawBoundNow$;
                    break;
                case 'when_not_rendering':
                    obs = this.isRendering$.pipe(switchMap((x) => (x ? EMPTY : this.rawBoundNow$)));
                    break;
                case 'only_after_render_finishes':
                    obs = this.isRendering$.pipe(onTrueToFalse(), switchMap((x) => this.rawBoundNow$.pipe(first())));
                    break;
            }
            return obs.pipe(throttleTime(throttleMs, undefined, { leading: true, trailing: true }));
        }));
    }), distinctUntilChanged(isSameLatLngBound), shareReplay(1));
    useVirtualBound$ = this.state$.pipe(map((x) => x.useVirtualBound), distinctUntilChanged(), shareReplay(1));
    bound$ = this.useVirtualBound$.pipe(switchMap((useVirtualBound) => {
        if (useVirtualBound) {
            return this.virtualBound$;
        }
        else {
            return this.rawBound$;
        }
    }), shareReplay(1));
    boundSizing$ = this.bound$.pipe(map((x) => diffLatLngBoundPoints(x)), shareReplay(1));
    boundWrapsAroundWorld$ = this.bound$.pipe(map((x) => latLngBoundWrapsMap(x)), distinctUntilChanged(), shareReplay(1));
    isWithinBoundFunction$ = this.bound$.pipe(map((x) => isWithinLatLngBoundFunction(x)), shareReplay(1));
    overlapsBoundFunction$ = this.virtualBound$.pipe(map((x) => overlapsLatLngBoundFunction(x)), shareReplay(1));
    zoomNow$ = this.whenInitialized$.pipe(switchMap(() => this.mapInstance$.pipe(switchMap((x) => this._renderingTimer.pipe(map(() => x.getZoom()))), shareReplay(1))));
    zoom$ = this.whenInitialized$.pipe(switchMap(() => {
        return this.isZooming$.pipe(onTrueToFalse(), startWith(undefined), switchMap(() => this.zoomNow$.pipe(first())), distinctUntilChanged(), shareReplay(1));
    }));
    pitchNow$ = this.whenInitialized$.pipe(switchMap(() => this.mapInstance$.pipe(switchMap((x) => this._movingTimer.pipe(map(() => x.getPitch()))), shareReplay(1))));
    pitch$ = this.whenInitialized$.pipe(switchMap(() => {
        return this.isRotating$.pipe(onTrueToFalse(), startWith(undefined), switchMap(() => this.pitchNow$.pipe(first())), distinctUntilChanged(), shareReplay(1));
    }));
    bearingNow$ = this.whenInitialized$.pipe(switchMap(() => this.mapInstance$.pipe(switchMap((x) => this._movingTimer.pipe(map(() => x.getBearing()))), shareReplay(1))));
    bearing$ = this.whenInitialized$.pipe(switchMap(() => {
        return this.isRotating$.pipe(onTrueToFalse(), startWith(undefined), switchMap(() => this.bearingNow$.pipe(first())), distinctUntilChanged(), shareReplay(1));
    }));
    drawerContent$ = this.state$.pipe(map((x) => x.drawerContent), distinctUntilChanged(), shareReplay(1));
    hasDrawerContent$ = this.drawerContent$.pipe(map((x) => x != null), distinctUntilChanged(), shareReplay(1));
    clickEvent$ = this.state$.pipe(map((x) => x.clickEvent), distinctUntilChanged(), shareReplay(1));
    doubleClickEvent$ = this.state$.pipe(map((x) => x.doubleClickEvent), distinctUntilChanged(), shareReplay(1));
    rightClickEvent$ = this.state$.pipe(map((x) => x.rightClickEvent), distinctUntilChanged(), shareReplay(1));
    // MARK: State Changes
    setMargin = this.updater((state, margin) => ({ ...state, margin: margin && (margin.rightMargin !== 0 || margin.leftMargin !== 0) ? margin : undefined }));
    setMinimumVirtualViewportSize = this.updater((state, minimumVirtualViewportSize) => ({ ...state, minimumVirtualViewportSize }));
    setUseVirtualBound = this.updater((state, useVirtualBound) => ({ ...state, useVirtualBound }));
    setBoundRefreshSettings = this.updater((state, boundRefreshSettings) => ({ ...state, boundRefreshSettings: { ...state.boundRefreshSettings, ...boundRefreshSettings } }));
    _setMapService = this.updater((state, mapService) => ({ mapService, moveState: 'init', lifecycleState: 'init', zoomState: 'init', rotateState: 'init', retainContent: state.retainContent, drawerContent: state.retainContent ? state.drawerContent : undefined, useVirtualBound: state.useVirtualBound, boundRefreshSettings: state.boundRefreshSettings }));
    _setLifecycleState = this.updater((state, lifecycleState) => ({ ...state, lifecycleState }));
    _setMoveState = this.updater((state, moveState) => ({ ...state, moveState }));
    _setZoomState = this.updater((state, zoomState) => ({ ...state, zoomState }));
    _setRotateState = this.updater((state, rotateState) => ({ ...state, rotateState }));
    _setMapCanvasSize = this.updater((state, mapCanvasSize) => ({ ...state, mapCanvasSize }));
    _setClickEvent = this.updater((state, clickEvent) => ({ ...state, clickEvent }));
    _setDoubleClickEvent = this.updater((state, doubleClickEvent) => ({ ...state, doubleClickEvent }));
    _setRightClickEvent = this.updater((state, rightClickEvent) => ({ ...state, rightClickEvent }));
    _setError = this.updater((state, error) => ({ ...state, error }));
    clearDrawerContent = this.updater((state) => setDrawerContent(state, undefined));
    setDrawerContent = this.updater(setDrawerContent);
    // MARK: Compat
    /**
     * @deprecated use drawerContent$ instead.
     */
    content$ = this.drawerContent$;
    /**
     * @deprecated use hasDrawerContent$ instead.
     */
    hasContent$ = this.hasDrawerContent$;
    /**
     * @deprecated use clearDrawerContent instead.
     */
    clearContent = this.updater((state) => setDrawerContent(state, undefined));
    /**
     * @deprecated use setDrawerContent instead.
     */
    setContent = this.updater(setDrawerContent);
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxMapStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxMapStore });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxMapStore, decorators: [{
            type: Injectable
        }], ctorParameters: () => [] });
function setDrawerContent(state, drawerContent) {
    return { ...state, drawerContent };
}

/**
 * Provided in the parent component that allows children to emit events related to their lifecycles.
 */
class DbxMapboxChangeService {
    dbxMapboxMapStore = inject(DbxMapboxMapStore);
    _markerDestroyed = new Subject();
    _applyChanges = new Subject();
    markerDestroyed$ = this._markerDestroyed;
    applyChanges$ = merge(this._applyChanges, this.markerDestroyed$).pipe(throttleTime(100, undefined, { leading: false, trailing: true }));
    _applyChangesSub = new SubscriptionObject(this.dbxMapboxMapStore.mapService$
        .pipe(switchMap((mapService) => this.applyChanges$.pipe(tap(() => {
        mapService.applyChanges();
    }))))
        .subscribe());
    applyChanges() {
        this._applyChanges.next();
    }
    emitMarkerDestroyed() {
        this._markerDestroyed.next();
    }
    ngOnDestroy() {
        this._markerDestroyed.complete();
        this._applyChanges.complete();
        this._applyChangesSub.destroy();
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxChangeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxChangeService, providedIn: null });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxChangeService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: null
                }]
        }] });

/**
 * Store used for storing injectable content into the map.
 */
class DbxMapboxInjectionStore extends ComponentStore {
    constructor() {
        super({
            map: new Map()
        });
    }
    map$ = this.state$.pipe(map((x) => x.map), distinctUntilMapHasDifferentKeys(), shareReplay(1));
    allInjectionConfigs$ = this.map$.pipe(map((x) => Array.from(x.values())), shareReplay(1));
    // MARK: State Changes
    addInjectionConfig = this.updater(updateDbxMapboxMapInjectionStoreStateWithInjectionConfig);
    removeInjectionConfigWithKey = this.updater(updateDbxMapboxMapInjectionStoreStateWithRemovedKey);
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxInjectionStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxInjectionStore });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxInjectionStore, decorators: [{
            type: Injectable
        }], ctorParameters: () => [] });
function updateDbxMapboxMapInjectionStoreStateWithInjectionConfig(state, config) {
    const map = new Map(state.map).set(config.key, config);
    return { ...state, map };
}
function updateDbxMapboxMapInjectionStoreStateWithRemovedKey(state, key) {
    // only create a new state if the key is going to get removed
    if (state.map.has(key)) {
        const map = new Map(state.map);
        map.delete(key);
        state = { ...state, map };
    }
    return state;
}

/**
 * Injects the components configured in the DbxMapboxInjectionStore into the view.
 */
class DbxMapboxInjectionComponent {
    dbxMapboxMapKeyInjectionStore = inject(DbxMapboxInjectionStore);
    entriesSignal = toSignal(this.dbxMapboxMapKeyInjectionStore.allInjectionConfigs$);
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxInjectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: DbxMapboxInjectionComponent, isStandalone: true, selector: "dbx-mapbox-injection", ngImport: i0, template: `
    <dbx-injection-array [entries]="entriesSignal()"></dbx-injection-array>
  `, isInline: true, dependencies: [{ kind: "component", type: DbxInjectionArrayComponent, selector: "dbx-injection-array", inputs: ["entries"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxInjectionComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'dbx-mapbox-injection',
                    template: `
    <dbx-injection-array [entries]="entriesSignal()"></dbx-injection-array>
  `,
                    imports: [DbxInjectionArrayComponent],
                    changeDetection: ChangeDetectionStrategy.OnPush,
                    standalone: true
                }]
        }] });

/**
 * Token used by provideMapboxInjectionStoreIfDoesNotExist() to prevent injecting a parent DbxMapboxInjectionStore into the child view.
 */
class DbxMapboxInjectionStoreProviderBlock {
    dbxMapboxInjectionStore = inject(DbxMapboxInjectionStore, { skipSelf: true });
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxInjectionStoreProviderBlock, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxInjectionStoreProviderBlock });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxInjectionStoreProviderBlock, decorators: [{
            type: Injectable
        }] });
class DbxMapboxInjectionStoreInjectionBlockDirective {
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxInjectionStoreInjectionBlockDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: DbxMapboxInjectionStoreInjectionBlockDirective, isStandalone: true, selector: "[dbxMapboxInjectionStoreParentBlocker]", providers: [DbxMapboxInjectionStoreProviderBlock], ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxInjectionStoreInjectionBlockDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[dbxMapboxInjectionStoreParentBlocker]',
                    providers: [DbxMapboxInjectionStoreProviderBlock],
                    standalone: true
                }]
        }] });
/**
 * Creates a Provider that initializes a new DbxMapboxInjectionStore if a parent does not exist.
 *
 * If a DbxMapboxInjectionStoreInjectionBlock is available in the context, and references the same dbxMapboxInjectionStore that is attempting to be injected, a new DbxMapboxInjectionStore is created.
 *
 * @returns
 */
function provideMapboxInjectionStoreIfParentIsUnavailable() {
    return {
        provide: DbxMapboxInjectionStore,
        useFactory: (parentInjector, dbxMapboxInjectionStoreInjectionBlock, dbxMapboxInjectionStore) => {
            if (!dbxMapboxInjectionStore || (dbxMapboxInjectionStore && dbxMapboxInjectionStoreInjectionBlock != null && dbxMapboxInjectionStoreInjectionBlock.dbxMapboxInjectionStore === dbxMapboxInjectionStore)) {
                // create a new dbxMapboxInjectionStore to use
                const injector = Injector.create({ providers: [{ provide: DbxMapboxInjectionStore }], parent: parentInjector });
                dbxMapboxInjectionStore = injector.get(DbxMapboxInjectionStore);
            }
            return dbxMapboxInjectionStore;
        },
        deps: [Injector, [new Optional(), DbxMapboxInjectionStoreProviderBlock], [new Optional(), new SkipSelf(), DbxMapboxInjectionStore]]
    };
}

/**
 * Directive that configures a MapComponent with content from DbxMapboxService. Connects a host MapService to a parent DbxMapboxMapStore if available.
 */
class DbxMapboxMapDirective {
    mapService = inject(MapService, { host: true });
    mapboxMap = inject(MapComponent, { host: true });
    dbxMapboxService = inject(DbxMapboxService);
    dbxMapboxMapStore = inject(DbxMapboxMapStore, { optional: true });
    ngOnInit() {
        if (this.dbxMapboxMapStore) {
            this.dbxMapboxMapStore.setMapService(this.mapService);
        }
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxMapDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: DbxMapboxMapDirective, isStandalone: true, selector: "[dbxMapboxMap]", providers: [
            {
                provide: MAP_COMPONENT_INITIALIZATION_OPTIONS,
                useFactory: (dbxMapboxService) => dbxMapboxService.initializationOptions(),
                deps: [DbxMapboxService]
            }
        ], ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxMapDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[dbxMapboxMap]',
                    providers: [
                        {
                            provide: MAP_COMPONENT_INITIALIZATION_OPTIONS,
                            useFactory: (dbxMapboxService) => dbxMapboxService.initializationOptions(),
                            deps: [DbxMapboxService]
                        }
                    ],
                    standalone: true
                }]
        }] });

/**
 * Content drawer that connects with DbxMapboxMapStore to show the content.
 */
class DbxMapboxLayoutDrawerComponent {
    dbxMapboxMapStore = inject(DbxMapboxMapStore);
    drawerConfigSignal = toSignal(this.dbxMapboxMapStore.drawerContent$);
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxLayoutDrawerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: DbxMapboxLayoutDrawerComponent, isStandalone: true, selector: "dbx-mapbox-layout-drawer", host: { classAttribute: "dbx-mapbox-layout-drawer" }, ngImport: i0, template: "<div>\n  <dbx-injection [config]=\"drawerConfigSignal()\"></dbx-injection>\n</div>\n", dependencies: [{ kind: "component", type: DbxInjectionComponent, selector: "dbx-injection, [dbxInjection], [dbx-injection]", inputs: ["config", "template"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxLayoutDrawerComponent, decorators: [{
            type: Component,
            args: [{ selector: 'dbx-mapbox-layout-drawer', host: {
                        class: 'dbx-mapbox-layout-drawer'
                    }, imports: [DbxInjectionComponent], standalone: true, template: "<div>\n  <dbx-injection [config]=\"drawerConfigSignal()\"></dbx-injection>\n</div>\n" }]
        }] });

/**
 * Responsive component meant to split a left and right column.
 *
 * The left column is smaller than the right column, which contains the primary content.
 *
 * Requires a TwoColumnsContextStore to be provided.
 */
class DbxMapboxLayoutComponent {
    dbxMapboxMapStore = inject(DbxMapboxMapStore);
    _viewResized = new Subject();
    _refreshContentMargins = new Subject();
    drawerOpenedChange = output();
    drawerContainer = viewChild.required(MatDrawerContainer);
    drawerContainerElement = viewChild.required(MatDrawerContainer, { read: (ElementRef) });
    drawerContent = viewChild.required('drawerContent');
    side = input('right', { transform: (x) => x || 'right' });
    mode = input('side', { transform: (x) => x || 'side' });
    /**
     * Forces the drawer to assume the drawer has content if true, or assume it has no content if false.
     */
    forceHasDrawerContent = input(undefined);
    drawerButtonColor = input('background', { transform: (x) => x ?? 'background' });
    openDrawer = input(undefined); // input open/close drawer config
    isDrawerOpenSignal = signal(undefined); // Signal to toggle the drawer
    _openDrawerEffect = effect(() => {
        this.isDrawerOpenSignal.set(this.openDrawer());
    }, { allowSignalWrites: true });
    storeHasDrawerContent = toSignal(this.dbxMapboxMapStore.hasDrawerContent$);
    drawerHasContentSignal = computed(() => this.forceHasDrawerContent() ?? this.storeHasDrawerContent());
    refreshContentMargins$ = this._refreshContentMargins;
    isOpenAndHasContentSignal = computed(() => {
        return this.drawerHasContentSignal() && this.isDrawerOpenSignal();
    });
    viewResized$ = this._viewResized.asObservable();
    side$ = toObservable(this.side);
    mode$ = toObservable(this.mode);
    drawerHasContent$ = toObservable(this.drawerHasContentSignal);
    isOpenAndHasContent$ = toObservable(this.isOpenAndHasContentSignal);
    positionSignal = computed(() => {
        return this.side() === 'right' ? 'end' : 'start';
    });
    drawerClassesSignal = computed(() => {
        const side = this.side();
        const hasContent = this.drawerHasContentSignal();
        const isOpen = this.isDrawerOpenSignal(); // NOTE: isOpenAndHasContentSignal is not used here
        return (hasContent ? 'has-drawer-content' : 'no-drawer-content') + ` ${side}-drawer ` + (isOpen ? 'open-drawer' : '');
    });
    buttonIconSignal = computed(() => {
        const side = this.side();
        const opened = this.isDrawerOpenSignal(); // NOTE: isOpenAndHasContentSignal is not used here
        let icons = ['chevron_right', 'chevron_left'];
        if (side === 'left') {
            icons = icons.reverse();
        }
        return opened ? icons[0] : icons[1];
    });
    _reszieSyncSub = new SubscriptionObject();
    _toggleSyncSub = new SubscriptionObject();
    ngOnInit() {
        this._reszieSyncSub.subscription = this.side$.pipe(switchMap(() => this._viewResized.pipe(throttleTime(80, undefined, { leading: true, trailing: true }), map(() => 'r'), startWith('s')))).subscribe((reason) => {
            this.dbxMapboxMapStore.mapInstance$.subscribe((x) => {
                x.resize();
                // side changed
                if (reason === 's') {
                    this._refreshContentMargins.next();
                }
            });
        });
        let init = false;
        this._toggleSyncSub.subscription = this.mode$
            .pipe(switchMap((mode) => {
            let obs;
            if (mode === 'push') {
                obs = combineLatest([this.isOpenAndHasContent$.pipe(distinctUntilChanged()), this.refreshContentMargins$]).pipe(tap(([opened]) => {
                    const drawerContainer = this.drawerContainer();
                    let { right } = drawerContainer._contentMargins;
                    drawerContainer.updateContentMargins();
                    setTimeout(() => {
                        const flip = opened ? 1 : -1;
                        if (opened) {
                            right = drawerContainer._contentMargins.right;
                        }
                        right = (right || 0) * flip;
                        const element = this.drawerContent().nativeElement;
                        const width = element.clientWidth;
                        const margin = {
                            leftMargin: 0,
                            rightMargin: right,
                            fullWidth: width
                        };
                        const easeTo = this.dbxMapboxMapStore.calculateNextCenterOffsetWithScreenMarginChange(margin).pipe(first(), map((center) => ({ to: { center, duration: 3200, essential: false } })));
                        this.dbxMapboxMapStore.setMargin(opened ? margin : undefined);
                        if (!init) {
                            this.dbxMapboxMapStore.easeTo(easeTo);
                        }
                        else {
                            init = true;
                        }
                    });
                }));
            }
            else {
                obs = combineLatest([this.isOpenAndHasContent$.pipe(distinctUntilChanged()), this._refreshContentMargins.pipe(delay(0))]).pipe(switchMap((_) => this.dbxMapboxMapStore.mapInstance$), tap((map) => {
                    this.drawerContainer().updateContentMargins();
                    map.triggerRepaint();
                }));
            }
            return obs;
        }))
            .subscribe();
    }
    ngOnDestroy() {
        this._viewResized.complete();
        this._refreshContentMargins.complete();
        this._reszieSyncSub.destroy();
        this._toggleSyncSub.destroy();
    }
    viewResized(event) {
        this._viewResized.next(event);
    }
    drawerOpened(opened) {
        const currentToggleState = this.isDrawerOpenSignal();
        if (currentToggleState !== opened) {
            this.toggleDrawer(opened); // sync with drawer toggling
            this.drawerOpenedChange.emit(opened);
        }
    }
    toggleDrawer(open) {
        if (open == null) {
            open = !this.isDrawerOpenSignal();
        }
        this.isDrawerOpenSignal.set(open);
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "18.2.13", type: DbxMapboxLayoutComponent, isStandalone: true, selector: "dbx-mapbox-layout", inputs: { side: { classPropertyName: "side", publicName: "side", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, forceHasDrawerContent: { classPropertyName: "forceHasDrawerContent", publicName: "forceHasDrawerContent", isSignal: true, isRequired: false, transformFunction: null }, drawerButtonColor: { classPropertyName: "drawerButtonColor", publicName: "drawerButtonColor", isSignal: true, isRequired: false, transformFunction: null }, openDrawer: { classPropertyName: "openDrawer", publicName: "openDrawer", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { drawerOpenedChange: "drawerOpenedChange" }, viewQueries: [{ propertyName: "drawerContainer", first: true, predicate: MatDrawerContainer, descendants: true, isSignal: true }, { propertyName: "drawerContainerElement", first: true, predicate: MatDrawerContainer, descendants: true, read: ElementRef, isSignal: true }, { propertyName: "drawerContent", first: true, predicate: ["drawerContent"], descendants: true, isSignal: true }], ngImport: i0, template: "<mat-drawer-container #containerElement class=\"dbx-mapbox-layout-container\" [ngClass]=\"drawerClassesSignal()\" [hasBackdrop]=\"false\">\n  <mat-drawer class=\"dbx-mapbox-layout-drawer\" #drawer (openedChange)=\"drawerOpened($event)\" [opened]=\"isOpenAndHasContentSignal()\" [mode]=\"mode()\" [position]=\"positionSignal()\">\n    <div class=\"dbx-mapbox-layout-drawer-content\" [ngClass]=\"drawerClassesSignal()\">\n      <ng-content select=\"[drawer]\"></ng-content>\n      <dbx-mapbox-layout-drawer></dbx-mapbox-layout-drawer>\n    </div>\n  </mat-drawer>\n  <mat-drawer-content #content class=\"dbx-mapbox-layout-content\" (dbxResized)=\"viewResized($event)\">\n    <button mat-icon-button (click)=\"toggleDrawer()\" class=\"dbx-mapbox-layout-drawer-button\" [dbxColor]=\"drawerButtonColor()\">\n      <mat-icon>{{ buttonIconSignal() }}</mat-icon>\n    </button>\n    <ng-content></ng-content>\n  </mat-drawer-content>\n</mat-drawer-container>\n", styles: [".dbx-mapbox-layout-container{height:100%;max-width:100%}.dbx-mapbox-layout-container .mat-drawer-container{height:100%}.dbx-mapbox-layout-container .dbx-mapbox-layout-drawer{max-width:calc(100% - var(--dbx-mapbox-min-width-var, 33px))}.dbx-mapbox-layout-container .dbx-mapbox-layout-drawer-content{height:100%;width:100%;overflow:hidden}.dbx-mapbox-layout-content>.dbx-mapbox-layout-drawer-button{position:absolute;z-index:2;top:40%;border:none;display:flex;overflow:hidden}.dbx-mapbox-layout-content>.dbx-mapbox-layout-drawer-button.mat-mdc-icon-button{padding-left:0}.dbx-mapbox-layout-content>.dbx-mapbox-layout-drawer-button.mat-mdc-icon-button ::ng-deep>.mat-mdc-button-persistent-ripple{border-radius:unset}.left-drawer .dbx-mapbox-layout-content>.dbx-mapbox-layout-drawer-button{left:0;border-radius:0 20px 20px 0}.right-drawer .dbx-mapbox-layout-content>.dbx-mapbox-layout-drawer-button{right:0;border-radius:20px 0 0 20px}.has-drawer-content .dbx-mapbox-layout-content>.dbx-mapbox-layout-drawer-button{width:35px}.has-drawer-content.open-drawer .dbx-mapbox-layout-content>.dbx-mapbox-layout-drawer-button{width:35px}.no-drawer-content .dbx-mapbox-layout-content>.dbx-mapbox-layout-drawer-button{width:0px}.dbx-mapbox-layout-content>.dbx-mapbox-layout-drawer-button mat-icon{padding-left:8px}\n"], dependencies: [{ kind: "directive", type: DbxResizedDirective, selector: "[dbxResized]", outputs: ["dbxResized"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: DbxMapboxLayoutDrawerComponent, selector: "dbx-mapbox-layout-drawer" }, { kind: "component", type: MatDrawer, selector: "mat-drawer", inputs: ["position", "mode", "disableClose", "autoFocus", "opened"], outputs: ["openedChange", "opened", "openedStart", "closed", "closedStart", "positionChanged"], exportAs: ["matDrawer"] }, { kind: "component", type: MatDrawerContainer, selector: "mat-drawer-container", inputs: ["autosize", "hasBackdrop"], outputs: ["backdropClick"], exportAs: ["matDrawerContainer"] }, { kind: "component", type: MatDrawerContent, selector: "mat-drawer-content" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "directive", type: DbxColorDirective, selector: "[dbxColor]", inputs: ["dbxColor"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxLayoutComponent, decorators: [{
            type: Component,
            args: [{ selector: 'dbx-mapbox-layout', imports: [DbxResizedDirective, NgClass, DbxMapboxLayoutDrawerComponent, MatDrawer, MatDrawerContainer, MatDrawerContent, MatIconModule, MatIconButton, DbxColorDirective], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, template: "<mat-drawer-container #containerElement class=\"dbx-mapbox-layout-container\" [ngClass]=\"drawerClassesSignal()\" [hasBackdrop]=\"false\">\n  <mat-drawer class=\"dbx-mapbox-layout-drawer\" #drawer (openedChange)=\"drawerOpened($event)\" [opened]=\"isOpenAndHasContentSignal()\" [mode]=\"mode()\" [position]=\"positionSignal()\">\n    <div class=\"dbx-mapbox-layout-drawer-content\" [ngClass]=\"drawerClassesSignal()\">\n      <ng-content select=\"[drawer]\"></ng-content>\n      <dbx-mapbox-layout-drawer></dbx-mapbox-layout-drawer>\n    </div>\n  </mat-drawer>\n  <mat-drawer-content #content class=\"dbx-mapbox-layout-content\" (dbxResized)=\"viewResized($event)\">\n    <button mat-icon-button (click)=\"toggleDrawer()\" class=\"dbx-mapbox-layout-drawer-button\" [dbxColor]=\"drawerButtonColor()\">\n      <mat-icon>{{ buttonIconSignal() }}</mat-icon>\n    </button>\n    <ng-content></ng-content>\n  </mat-drawer-content>\n</mat-drawer-container>\n", styles: [".dbx-mapbox-layout-container{height:100%;max-width:100%}.dbx-mapbox-layout-container .mat-drawer-container{height:100%}.dbx-mapbox-layout-container .dbx-mapbox-layout-drawer{max-width:calc(100% - var(--dbx-mapbox-min-width-var, 33px))}.dbx-mapbox-layout-container .dbx-mapbox-layout-drawer-content{height:100%;width:100%;overflow:hidden}.dbx-mapbox-layout-content>.dbx-mapbox-layout-drawer-button{position:absolute;z-index:2;top:40%;border:none;display:flex;overflow:hidden}.dbx-mapbox-layout-content>.dbx-mapbox-layout-drawer-button.mat-mdc-icon-button{padding-left:0}.dbx-mapbox-layout-content>.dbx-mapbox-layout-drawer-button.mat-mdc-icon-button ::ng-deep>.mat-mdc-button-persistent-ripple{border-radius:unset}.left-drawer .dbx-mapbox-layout-content>.dbx-mapbox-layout-drawer-button{left:0;border-radius:0 20px 20px 0}.right-drawer .dbx-mapbox-layout-content>.dbx-mapbox-layout-drawer-button{right:0;border-radius:20px 0 0 20px}.has-drawer-content .dbx-mapbox-layout-content>.dbx-mapbox-layout-drawer-button{width:35px}.has-drawer-content.open-drawer .dbx-mapbox-layout-content>.dbx-mapbox-layout-drawer-button{width:35px}.no-drawer-content .dbx-mapbox-layout-content>.dbx-mapbox-layout-drawer-button{width:0px}.dbx-mapbox-layout-content>.dbx-mapbox-layout-drawer-button mat-icon{padding-left:8px}\n"] }]
        }] });

/**
 * Directive that connects a host MatMenuTrigger to a DbxMapboxMapStore and listens for right-clicks on the map.
 *
 * The map dissapears if the mouse scrolls anywhere else on the map.
 */
class DbxMapboxMenuComponent extends AbstractSubscriptionDirective {
    dbxMapboxMapStore = inject(DbxMapboxMapStore);
    matMenuTrigger = inject(MatMenuTrigger, { host: true });
    active = input(true, { transform: isNotFalse });
    openCloseSignal = signal(undefined);
    posSignal = signal({ x: `0`, y: `0` });
    _openCloseEffect = effect(() => {
        const openOrClose = this.openCloseSignal();
        switch (openOrClose) {
            case true:
                this.matMenuTrigger.openMenu();
                break;
            case false:
                this.matMenuTrigger.closeMenu();
                break;
        }
    });
    _menuCloseSub = new SubscriptionObject();
    _preventRightClick = new DestroyFunctionObject();
    active$ = toObservable(this.active);
    ngOnInit() {
        this.sub = this.active$
            .pipe(switchMap((active) => {
            if (active) {
                return this.dbxMapboxMapStore.rightClickEvent$;
            }
            else {
                return of();
            }
        }), filter(Boolean))
            .subscribe((event) => {
            const menu = this.matMenuTrigger.menu;
            const buttonEvent = event.originalEvent;
            if (menu && buttonEvent) {
                buttonEvent.preventDefault();
                // update position of this component for menu to open at
                this.posSignal.set({
                    x: `${buttonEvent.x}px`,
                    y: `${buttonEvent.y}px`
                });
                // open menu
                this.matMenuTrigger.openMenu();
                // prevent right clicks in the cdkOverlay while the menu is open
                this._preventRightClick.destroy = disableRightClickInCdkBackdrop(undefined, () => {
                    this.matMenuTrigger.closeMenu();
                });
            }
        });
        this._menuCloseSub.subscription = this.matMenuTrigger.menuClosed.subscribe(() => {
            // destroy prevention when the menu is closed.
            this._preventRightClick.destroy();
        });
    }
    ngOnDestroy() {
        super.ngOnDestroy();
        this._menuCloseSub.destroy();
        this._preventRightClick.destroy();
        if (this.matMenuTrigger) {
            this.matMenuTrigger.closeMenu();
        }
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxMenuComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.13", type: DbxMapboxMenuComponent, isStandalone: true, selector: "dbx-mapbox-menu", inputs: { active: { classPropertyName: "active", publicName: "active", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.top": "posSignal().y", "style.left": "posSignal().x" }, styleAttribute: "visibility: hidden; position: fixed" }, usesInheritance: true, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxMenuComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'dbx-mapbox-menu',
                    template: '',
                    host: {
                        style: 'visibility: hidden; position: fixed',
                        '[style.top]': 'posSignal().y',
                        '[style.left]': 'posSignal().x'
                    },
                    changeDetection: ChangeDetectionStrategy.OnPush,
                    standalone: true
                }]
        }] });

/**
 * Token used by provideMapboxStoreIfDoesNotExist() to prevent injecting a parent DbxMapboxMapStore into the child view.
 */
class DbxMapboxMapStoreProviderBlock {
    dbxMapboxMapStore = inject(DbxMapboxMapStore, { skipSelf: true });
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxMapStoreProviderBlock, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxMapStoreProviderBlock });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxMapStoreProviderBlock, decorators: [{
            type: Injectable
        }] });
class DbxMapboxMapStoreInjectionBlockDirective {
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxMapStoreInjectionBlockDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: DbxMapboxMapStoreInjectionBlockDirective, isStandalone: true, selector: "[dbxMapboxStoreParentBlocker]", providers: [DbxMapboxMapStoreProviderBlock], ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxMapStoreInjectionBlockDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[dbxMapboxStoreParentBlocker]',
                    providers: [DbxMapboxMapStoreProviderBlock],
                    standalone: true
                }]
        }] });
/**
 * Creates a Provider that initializes a new DbxMapboxMapStore if a parent does not exist.
 *
 * If a DbxMapboxMapStoreInjectionBlock is available in the context, and references the same dbxMapboxMapStore that is attempting to be injected, a new DbxMapboxMapStore is created.
 *
 * @returns
 */
function provideMapboxStoreIfParentIsUnavailable() {
    return {
        provide: DbxMapboxMapStore,
        useFactory: (parentInjector, dbxMapboxMapStoreInjectionBlock, dbxMapboxMapStore) => {
            if (!dbxMapboxMapStore || (dbxMapboxMapStore && dbxMapboxMapStoreInjectionBlock != null && dbxMapboxMapStoreInjectionBlock.dbxMapboxMapStore === dbxMapboxMapStore)) {
                // create a new dbxMapboxMapStore to use
                const injector = Injector.create({ providers: [{ provide: DbxMapboxMapStore }], parent: parentInjector });
                dbxMapboxMapStore = injector.get(DbxMapboxMapStore);
            }
            return dbxMapboxMapStore;
        },
        deps: [Injector, [new Optional(), DbxMapboxMapStoreProviderBlock], [new Optional(), new SkipSelf(), DbxMapboxMapStore]]
    };
}

class DbxMapboxMarkerComponent {
    _dbxMapboxChangeService = inject(DbxMapboxChangeService, { optional: true });
    static _latLngPoint = latLngPointFunction({ wrap: true });
    marker = input.required();
    latLngSignal = computed(() => {
        const marker = this.marker();
        return marker?.latLng ? DbxMapboxMarkerComponent._latLngPoint(marker.latLng) : undefined;
    });
    presentationSignal = computed(() => this.marker()?.presentation ?? 'normal');
    styleSignal = computed(() => {
        const marker = this.marker();
        let width = 0;
        let height = 0;
        const size = marker?.size || 'medium';
        switch (marker?.presentation) {
            case 'normal':
                if (typeof size === 'number') {
                    width = size;
                }
                else {
                    switch (size) {
                        case 'small':
                            width = 18;
                            break;
                        case 'medium':
                            width = 24;
                            break;
                        case 'large':
                            width = 32;
                            break;
                        case 'tall':
                            width = 24;
                            height = 32;
                            break;
                    }
                    break;
                }
                break;
        }
        if (!height) {
            height = width;
        }
        const imageInput = marker?.image;
        const image = imageInput ? (typeof imageInput === 'string' ? imageInput : getValueFromGetter(imageInput, width)) : undefined;
        const style = {
            ...marker?.style,
            'background-image': image
        };
        if (width && height) {
            style.width = width + 'px';
            style.height = height + 'px';
            style['font-size'] = width + 'px';
        }
        return style;
    });
    presentationCssClassSignal = computed(() => {
        const marker = this.marker();
        const presentation = this.presentationSignal();
        const markerClasses = marker?.markerClasses;
        let cssClasses = [];
        switch (presentation) {
            case 'chip':
            case 'chip-small':
                cssClasses = ['dbx-mapbox-marker-chip', 'dbx-chip', 'mat-standard-chip', 'dbx-bg'];
                if (presentation === 'chip-small') {
                    cssClasses.push('dbx-chip-small');
                }
                break;
        }
        if (!marker?.icon) {
            cssClasses.push('dbx-mapbox-marker-no-icon');
        }
        if (markerClasses) {
            pushItemOrArrayItemsIntoArray(cssClasses, markerClasses);
        }
        return spaceSeparatedCssClasses(cssClasses);
    });
    ngOnDestroy() {
        this._dbxMapboxChangeService?.emitMarkerDestroyed();
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxMarkerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: DbxMapboxMarkerComponent, isStandalone: true, selector: "dbx-mapbox-marker", inputs: { marker: { classPropertyName: "marker", publicName: "marker", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
    <mgl-marker [lngLat]="latLngSignal()">
      <dbx-anchor [anchor]="marker()?.anchor">
        <div class="dbx-mapbox-marker" [ngClass]="presentationCssClassSignal()">
          <div class="dbx-mapbox-marker-icon-content" [ngStyle]="styleSignal()">
            @if (marker()?.icon) {
              <mat-icon>{{ marker()?.icon }}</mat-icon>
            }
          </div>
          @if (marker()?.label) {
            <div class="dbx-mapbox-marker-label dbx-outlined-text">{{ marker()?.label }}</div>
          }
        </div>
      </dbx-anchor>
    </mgl-marker>
  `, isInline: true, styles: [".dbx-mapbox-marker{display:flex;align-items:center;flex-direction:column}.dbx-mapbox-marker .dbx-mapbox-marker-icon-content{display:flex;align-items:center;justify-content:center}.dbx-mapbox-marker .dbx-mapbox-marker-icon-content mat-icon{width:100%;height:100%;font-size:inherit}.dbx-mapbox-marker .dbx-mapbox-marker-label{font-size:.9em}.dbx-mapbox-marker.dbx-mapbox-marker-chip.dbx-chip{flex-direction:row;font-size:1em}.dbx-mapbox-marker.dbx-mapbox-marker-chip.dbx-chip .dbx-mapbox-marker-icon-content{width:18px;height:18px;font-size:18px}.dbx-mapbox-marker.dbx-mapbox-marker-chip.dbx-chip.dbx-chip-small .dbx-mapbox-marker-label{padding-left:3px}.dbx-mapbox-marker.dbx-mapbox-marker-chip.dbx-chip.dbx-chip-small .dbx-mapbox-marker-icon-content{padding:0!important;width:16px;height:16px;font-size:16px}.dbx-mapbox-marker.dbx-mapbox-marker-chip.dbx-chip.dbx-mapbox-marker-no-icon>.dbx-mapbox-marker-icon-content{display:none}.dbx-mapbox-marker.dbx-mapbox-marker-chip.dbx-chip.dbx-mapbox-marker-no-icon>.dbx-mapbox-marker-icon-content .dbx-mapbox-marker-label{padding-left:0}.dbx-mapbox-marker.dbx-mapbox-marker-chip.dbx-chip .dbx-mapbox-marker-label{padding-left:4px}\n"], dependencies: [{ kind: "component", type: MarkerComponent, selector: "mgl-marker", inputs: ["offset", "anchor", "clickTolerance", "feature", "lngLat", "draggable", "popupShown", "className", "zIndex", "pitchAlignment", "rotationAlignment"], outputs: ["markerDragStart", "markerDragEnd", "markerDrag"] }, { kind: "component", type: DbxAnchorComponent, selector: "dbx-anchor, [dbx-anchor]", inputs: ["block"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxMarkerComponent, decorators: [{
            type: Component,
            args: [{ selector: 'dbx-mapbox-marker', template: `
    <mgl-marker [lngLat]="latLngSignal()">
      <dbx-anchor [anchor]="marker()?.anchor">
        <div class="dbx-mapbox-marker" [ngClass]="presentationCssClassSignal()">
          <div class="dbx-mapbox-marker-icon-content" [ngStyle]="styleSignal()">
            @if (marker()?.icon) {
              <mat-icon>{{ marker()?.icon }}</mat-icon>
            }
          </div>
          @if (marker()?.label) {
            <div class="dbx-mapbox-marker-label dbx-outlined-text">{{ marker()?.label }}</div>
          }
        </div>
      </dbx-anchor>
    </mgl-marker>
  `, imports: [MarkerComponent, DbxAnchorComponent, MatIconModule, NgStyle, NgClass], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, styles: [".dbx-mapbox-marker{display:flex;align-items:center;flex-direction:column}.dbx-mapbox-marker .dbx-mapbox-marker-icon-content{display:flex;align-items:center;justify-content:center}.dbx-mapbox-marker .dbx-mapbox-marker-icon-content mat-icon{width:100%;height:100%;font-size:inherit}.dbx-mapbox-marker .dbx-mapbox-marker-label{font-size:.9em}.dbx-mapbox-marker.dbx-mapbox-marker-chip.dbx-chip{flex-direction:row;font-size:1em}.dbx-mapbox-marker.dbx-mapbox-marker-chip.dbx-chip .dbx-mapbox-marker-icon-content{width:18px;height:18px;font-size:18px}.dbx-mapbox-marker.dbx-mapbox-marker-chip.dbx-chip.dbx-chip-small .dbx-mapbox-marker-label{padding-left:3px}.dbx-mapbox-marker.dbx-mapbox-marker-chip.dbx-chip.dbx-chip-small .dbx-mapbox-marker-icon-content{padding:0!important;width:16px;height:16px;font-size:16px}.dbx-mapbox-marker.dbx-mapbox-marker-chip.dbx-chip.dbx-mapbox-marker-no-icon>.dbx-mapbox-marker-icon-content{display:none}.dbx-mapbox-marker.dbx-mapbox-marker-chip.dbx-chip.dbx-mapbox-marker-no-icon>.dbx-mapbox-marker-icon-content .dbx-mapbox-marker-label{padding-left:0}.dbx-mapbox-marker.dbx-mapbox-marker-chip.dbx-chip .dbx-mapbox-marker-label{padding-left:4px}\n"] }]
        }] });

/**
 * Component used to render a set of DbxMapboxMarker values from the input data and marker factory.
 */
class DbxMapboxMarkersComponent {
    data = input.required();
    markerFactory = input.required();
    markersSignal = computed(() => {
        const data = this.data();
        const markerFactory = this.markerFactory();
        if (data?.length && markerFactory) {
            return data.map(markerFactory);
        }
        else {
            return [];
        }
    });
    trackMarkerById(index, marker) {
        return marker.id ?? `__MID__${index}_`;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxMarkersComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: DbxMapboxMarkersComponent, isStandalone: true, selector: "dbx-mapbox-markers", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, markerFactory: { classPropertyName: "markerFactory", publicName: "markerFactory", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
    @for (marker of markersSignal(); track trackMarkerById($index, marker)) {
      <dbx-mapbox-marker [marker]="marker"></dbx-mapbox-marker>
    }
  `, isInline: true, dependencies: [{ kind: "component", type: DbxMapboxMarkerComponent, selector: "dbx-mapbox-marker", inputs: ["marker"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxMarkersComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'dbx-mapbox-markers',
                    template: `
    @for (marker of markersSignal(); track trackMarkerById($index, marker)) {
      <dbx-mapbox-marker [marker]="marker"></dbx-mapbox-marker>
    }
  `,
                    imports: [DbxMapboxMarkerComponent],
                    changeDetection: ChangeDetectionStrategy.OnPush,
                    standalone: true
                }]
        }] });

/**
 * Directive that synchronizes a map's virtual size with the size of the element.
 */
class DbxMapboxLayoutVirtualResizeSyncComponent extends AbstractSubscriptionDirective {
    dbxMapboxLayoutComponent = inject(DbxMapboxLayoutComponent, { host: true });
    resizedVector$ = this.dbxMapboxLayoutComponent.viewResized$.pipe(map(() => {
        const element = this.dbxMapboxLayoutComponent.drawerContainerElement()?.nativeElement;
        const { clientWidth, clientHeight } = element;
        return {
            x: clientWidth,
            y: clientHeight
        };
    }), distinctUntilChanged(isSameVector), shareReplay(1));
    ngOnInit() {
        this.sub = this.dbxMapboxLayoutComponent.dbxMapboxMapStore.setMinimumVirtualViewportSize(this.resizedVector$);
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxLayoutVirtualResizeSyncComponent, deps: null, target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: DbxMapboxLayoutVirtualResizeSyncComponent, isStandalone: true, selector: "[dbxMapboxLayoutVirtualResizeSync]", usesInheritance: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxLayoutVirtualResizeSyncComponent, decorators: [{
            type: Directive,
            args: [{
                    selector: '[dbxMapboxLayoutVirtualResizeSync]',
                    standalone: true
                }]
        }] });

const importsAndExports = [
    //
    DbxMapboxLayoutVirtualResizeSyncComponent,
    DbxMapboxMapDirective,
    DbxMapboxLayoutComponent,
    DbxMapboxLayoutDrawerComponent,
    DbxMapboxInjectionComponent,
    DbxMapboxMenuComponent,
    DbxMapboxMarkerComponent,
    DbxMapboxMarkersComponent,
    DbxMapboxMapStoreInjectionBlockDirective,
    // ngx-mapbox-gl
    MapComponent,
    MarkerComponent
];
class DbxMapboxModule {
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
    static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxModule, imports: [
            //
            DbxMapboxLayoutVirtualResizeSyncComponent,
            DbxMapboxMapDirective,
            DbxMapboxLayoutComponent,
            DbxMapboxLayoutDrawerComponent,
            DbxMapboxInjectionComponent,
            DbxMapboxMenuComponent,
            DbxMapboxMarkerComponent,
            DbxMapboxMarkersComponent,
            DbxMapboxMapStoreInjectionBlockDirective,
            // ngx-mapbox-gl
            MapComponent,
            MarkerComponent], exports: [
            //
            DbxMapboxLayoutVirtualResizeSyncComponent,
            DbxMapboxMapDirective,
            DbxMapboxLayoutComponent,
            DbxMapboxLayoutDrawerComponent,
            DbxMapboxInjectionComponent,
            DbxMapboxMenuComponent,
            DbxMapboxMarkerComponent,
            DbxMapboxMarkersComponent,
            DbxMapboxMapStoreInjectionBlockDirective,
            // ngx-mapbox-gl
            MapComponent,
            MarkerComponent] });
    static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxModule, imports: [DbxMapboxLayoutComponent,
            DbxMapboxLayoutDrawerComponent,
            DbxMapboxInjectionComponent,
            DbxMapboxMarkerComponent,
            DbxMapboxMarkersComponent,
            // ngx-mapbox-gl
            MapComponent,
            MarkerComponent] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DbxMapboxModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: importsAndExports,
                    exports: importsAndExports
                }]
        }] });

/**
 * Creates EnvironmentProviders for providing DbxMapboxConfig and configuring the NgxMapboxGLModule.
 *
 * @param config Configuration
 * @returns EnvironmentProviders
 */
function provideDbxMapbox(config) {
    const { dbxMapboxConfig, ngxMapboxGLModuleConfig } = config;
    const providers = [
        // config
        {
            provide: DbxMapboxConfig,
            useValue: dbxMapboxConfig
        },
        // service
        DbxMapboxService,
        // ngxMapboxGL
        provideMapboxGL(ngxMapboxGLModuleConfig)
    ];
    return makeEnvironmentProviders(providers);
}

/**
 * Creates the styling for rendering a dot.
 *
 * @param background
 * @param color
 * @returns
 */
function dbxMapboxColoredDotStyle(background, color) {
    return {
        background,
        padding: '2px',
        color: (color ?? background) ? 'white' : undefined,
        'border-radius': '50%'
    };
}

const KNOWN_MAPBOX_STYLES = [
    // standard
    'mapbox://styles/mapbox/standard',
    // classic
    'mapbox://styles/mapbox/streets-v12',
    'mapbox://styles/mapbox/outdoors-v12',
    'mapbox://styles/mapbox/light-v11',
    'mapbox://styles/mapbox/dark-v11',
    'mapbox://styles/mapbox/satellite-v9',
    'mapbox://styles/mapbox/satellite-streets-v12',
    'mapbox://styles/mapbox/navigation-day-v1',
    'mapbox://styles/mapbox/navigation-night-v1'
];
const MAPBOX_MIN_ZOOM_LEVEL = 0;
const MAPBOX_MAX_ZOOM_LEVEL = 22;
function mapboxZoomLevel(input) {
    return Math.min(Math.max(input, MAPBOX_MIN_ZOOM_LEVEL), MAPBOX_MAX_ZOOM_LEVEL);
}

/**
 * Generated bundle index. Do not edit.
 */

export { DEFAULT_MAPBOX_CENTER, DEFAULT_MAPBOX_MAP_STORE_TIMER_REFRESH_PERIOD, DEFAULT_MAPBOX_STYLE, DEFAULT_MAPBOX_ZOOM, DbxMapboxChangeService, DbxMapboxConfig, DbxMapboxInjectionComponent, DbxMapboxInjectionStore, DbxMapboxInjectionStoreInjectionBlockDirective, DbxMapboxInjectionStoreProviderBlock, DbxMapboxLayoutComponent, DbxMapboxLayoutDrawerComponent, DbxMapboxLayoutVirtualResizeSyncComponent, DbxMapboxMapDirective, DbxMapboxMapStore, DbxMapboxMapStoreInjectionBlockDirective, DbxMapboxMapStoreProviderBlock, DbxMapboxMarkerComponent, DbxMapboxMarkersComponent, DbxMapboxMenuComponent, DbxMapboxModule, DbxMapboxService, KNOWN_MAPBOX_STYLES, MAPBOX_MAX_ZOOM_LEVEL, MAPBOX_MIN_ZOOM_LEVEL, dbxMapboxColoredDotStyle, filterByMapboxViewportBound, mapboxViewportBoundFunction, mapboxZoomLevel, provideDbxMapbox, provideMapboxInjectionStoreIfParentIsUnavailable, provideMapboxStoreIfParentIsUnavailable, updateDbxMapboxMapInjectionStoreStateWithInjectionConfig, updateDbxMapboxMapInjectionStoreStateWithRemovedKey };
//# sourceMappingURL=dereekb-dbx-web-mapbox.mjs.map
