UNPKG

vue3-maplibre-gl

Version:

Vue 3 components and composables for MapLibre GL JS - Build interactive maps with ease

1,317 lines (1,316 loc) 40.5 kB
import { defineComponent, ref, computed, unref, provide, watch, watchEffect, nextTick, onBeforeMount, onUnmounted, createElementBlock, openBlock, createCommentVNode, renderSlot, inject, onMounted, useSlots } from "vue"; import { u as useOptimizedComputed, a as useCreateMapbox, b as useMapEventListener, c as useLogger, d as useGeolocateControl, e as useGeolocateEventListener, f as useCreateGeoJsonSource, g as useDebouncedWatch, h as useCreateFillLayer, i as useLayerEventListener, j as useCreateCircleLayer, k as useCreateLineLayer, l as useCreateSymbolLayer, m as useCreateImage, n as useCreatePopup, o as useCreateMarker } from "./composables-Bz7jtADq.js"; const MapProvideKey = Symbol(); const SourceProvideKey = Symbol(); var MapCreationStatus = /* @__PURE__ */ ((MapCreationStatus2) => { MapCreationStatus2["NotInitialized"] = "not-initialized"; MapCreationStatus2["Initializing"] = "initializing"; MapCreationStatus2["Loading"] = "loading"; MapCreationStatus2["Loaded"] = "loaded"; MapCreationStatus2["Error"] = "error"; MapCreationStatus2["Destroyed"] = "destroyed"; return MapCreationStatus2; })(MapCreationStatus || {}); const MapboxEvents = [ "error", "load", "idle", "remove", "render", "resize", "webglcontextlost", "webglcontextrestored", "dataloading", "data", "tiledataloading", "sourcedataloading", "sourcedata", "styledata", "styleimagemissing", "dataabort", "sourcedataabort", "boxzoomcancel", "boxzoomstart", "boxzoomend", "touchcancel", "touchmove", "touchend", "touchstart", "click", "contextmenu", "dblclick", "mousemove", "mouseup", "mousedown", "mouseout", "mouseover", "movestart", "move", "moveend", "zoomstart", "zoom", "zoomend", "rotatestart", "rotate", "rotateend", "dragstart", "drag", "dragend", "pitchstart", "pitch", "pitchend", "wheel", "terrain" ]; const GeolocateEvents = [ "geolocate", "error", "outofmaxbounds", "trackuserlocationstart", "trackuserlocationend" ]; const MapboxLayerEvents = [ "click", "dblclick", "mousedown", "mouseup", "mousemove", "mouseenter", "mouseleave", "mouseover", "mouseout", "contextmenu", "touchstart", "touchend", "touchcancel" ]; const _hoisted_1$1 = { id: "maplibre_container" }; const _hoisted_2 = { key: 0 }; const _hoisted_3 = { key: 1 }; const _sfc_main$9 = /* @__PURE__ */ defineComponent({ __name: "Mapbox", props: { options: { default: () => ({ // Provide sensible defaults for better performance style: "https://demotiles.maplibre.org/style.json", center: [0, 0], zoom: 1, pitch: 0, bearing: 0, antialias: true, optimizeForTerrain: true, // Performance optimizations preserveDrawingBuffer: false, refreshExpiredTiles: true, maxTileCacheSize: null, localIdeographFontFamily: false, transformRequest: void 0, collectResourceTiming: false, fadeDuration: 300, crossSourceCollisions: true }) }, register: {}, debug: { type: Boolean, default: false }, autoCleanup: { type: Boolean, default: true }, containerId: { default: () => `maplibre-${Math.random().toString(36).substring(2, 11)}` }, containerClass: { default: "" }, onError: {}, onLoad: {} }, emits: ["register", "error", "load", "idle", "remove", "render", "resize", "webglcontextlost", "webglcontextrestored", "dataloading", "data", "tiledataloading", "dataabort", "sourcedataloading", "sourcedata", "sourcedataabort", "styledata", "styleimagemissing", "boxzoomcancel", "boxzoomstart", "boxzoomend", "touchcancel", "touchmove", "touchend", "touchstart", "click", "contextmenu", "dblclick", "mousemove", "mouseup", "mousedown", "mouseout", "mouseover", "movestart", "move", "moveend", "zoomstart", "zoom", "zoomend", "rotatestart", "rotate", "rotateend", "dragstart", "drag", "dragend", "pitchstart", "pitch", "pitchend", "wheel", "terrain"], setup(__props, { emit: __emit }) { const props = __props; const emits = __emit; const { logError } = useLogger(props.debug); const innerOptions = ref(); const maplibreElRef = ref(); const styleRef = ref(props.options.style); const isComponentMounted = ref(false); const mapCreationStatus = ref( MapCreationStatus.NotInitialized ); const mapOptions = useOptimizedComputed( () => { const baseOptions = { ...props.options }; const mergedOptions = { ...baseOptions, ...innerOptions.value }; if (!mergedOptions.container) { mergedOptions.container = props.containerId; } return mergedOptions; }, { deepEqual: true // Use deep equality for complex objects } ); const isMapReady = computed( () => mapCreationStatus.value === MapCreationStatus.Loaded ); const isMapLoading = computed( () => mapCreationStatus.value === MapCreationStatus.Loading ); const hasMapError = computed( () => mapCreationStatus.value === MapCreationStatus.Error ); function setMapOptions(options) { try { innerOptions.value = { ...unref(mapOptions) || {}, ...options }; } catch (error) { logError("Error setting map options:", error, { options }); } } function createMapContainer() { try { const wrapper = document.getElementById("maplibre_container"); if (!wrapper) { logError("Map container wrapper not found"); return null; } const existingContainer = document.getElementById(props.containerId); if (existingContainer) { existingContainer.remove(); } const container = document.createElement("div"); container.id = props.containerId; container.className = props.containerClass; container.style.width = "100%"; container.style.height = "100%"; wrapper.appendChild(container); return container; } catch (error) { logError("Error creating map container:", error); return null; } } const { mapInstance, setCenter, setBearing, setZoom, setPitch, setStyle, setMaxBounds, setMaxPitch, setMaxZoom, setMinPitch, setMinZoom, setRenderWorldCopies } = useCreateMapbox(maplibreElRef, styleRef, { ...unref(mapOptions), register: (actions) => { var _a, _b; try { const enhancedActions = { ...actions, setMapOptions, // Additional enhanced methods isMapReady: isMapReady.value, isMapLoading: isMapLoading.value, hasMapError: hasMapError.value }; (_a = props.register) == null ? void 0 : _a.call(props, enhancedActions); emits("register", enhancedActions); } catch (error) { logError("Error during map registration:", error); (_b = props.onError) == null ? void 0 : _b.call(props, error); } }, onLoad: (map) => { var _a, _b; try { mapCreationStatus.value = MapCreationStatus.Loaded; (_a = props.onLoad) == null ? void 0 : _a.call(props, map); } catch (error) { logError("Error in map load handler:", error); (_b = props.onError) == null ? void 0 : _b.call(props, error); } }, onError: (error) => { var _a; try { mapCreationStatus.value = MapCreationStatus.Error; logError("Map creation error:", error); (_a = props.onError) == null ? void 0 : _a.call(props, error); } catch (handlerError) { logError("Error in error handler:", handlerError); } }, debug: props.debug }); provide(MapProvideKey, mapInstance); MapboxEvents.map((evt) => { return useMapEventListener({ map: mapInstance, event: evt, on: (data) => { try { emits(evt, data); } catch (error) { logError(`Error in ${evt} event handler:`, error, { data }); } }, debug: props.debug }); }); const watchers = [ watch( () => unref(mapOptions).center, (value) => value && setCenter(value), { flush: "post" } ), watch( () => unref(mapOptions).bearing, (value) => value !== void 0 && setBearing(value), { flush: "post" } ), watch( () => unref(mapOptions).zoom, (value) => value !== void 0 && setZoom(value), { flush: "post" } ), watch( () => unref(mapOptions).pitch, (value) => value !== void 0 && setPitch(value), { flush: "post" } ), watch( () => unref(mapOptions).style, (value) => value && setStyle(value), { flush: "post" } ), watch( () => unref(mapOptions).maxBounds, (value) => value && setMaxBounds(value), { flush: "post" } ), watch( () => unref(mapOptions).maxPitch, (value) => value !== void 0 && value !== null && setMaxPitch(value), { flush: "post" } ), watch( () => unref(mapOptions).maxZoom, (value) => value !== void 0 && value !== null && setMaxZoom(value), { flush: "post" } ), watch( () => unref(mapOptions).minPitch, (value) => value !== void 0 && value !== null && setMinPitch(value), { flush: "post" } ), watch( () => unref(mapOptions).minZoom, (value) => value !== void 0 && value !== null && setMinZoom(value), { flush: "post" } ), watch( () => unref(mapOptions).renderWorldCopies, (value) => value !== void 0 && setRenderWorldCopies(value), { flush: "post" } ) ]; watchEffect(async () => { var _a; try { await nextTick(); const container = createMapContainer(); if (container) { maplibreElRef.value = container; isComponentMounted.value = true; mapCreationStatus.value = MapCreationStatus.Initializing; } else { logError("Failed to create map container"); mapCreationStatus.value = MapCreationStatus.Error; } } catch (error) { logError("Error in container creation watchEffect:", error); mapCreationStatus.value = MapCreationStatus.Error; (_a = props.onError) == null ? void 0 : _a.call(props, error); } }); function cleanup() { var _a; try { watchers.forEach((stopWatcher) => stopWatcher == null ? void 0 : stopWatcher()); (_a = maplibreElRef.value) == null ? void 0 : _a.remove(); isComponentMounted.value = false; mapCreationStatus.value = MapCreationStatus.Destroyed; } catch (error) { logError("Error during cleanup:", error); } } onBeforeMount(() => { if (props.autoCleanup) { cleanup(); } }); onUnmounted(() => { if (props.autoCleanup) { cleanup(); } }); return (_ctx, _cache) => { return openBlock(), createElementBlock("div", _hoisted_1$1, [ isMapLoading.value ? (openBlock(), createElementBlock("div", _hoisted_2, [ renderSlot(_ctx.$slots, "loading") ])) : createCommentVNode("", true), hasMapError.value ? (openBlock(), createElementBlock("div", _hoisted_3, [ renderSlot(_ctx.$slots, "error") ])) : createCommentVNode("", true), isMapReady.value || !isMapLoading.value && !hasMapError.value ? renderSlot(_ctx.$slots, "default", { key: 2 }) : createCommentVNode("", true) ]); }; } }); const _hoisted_1 = { key: 0 }; const _sfc_main$8 = /* @__PURE__ */ defineComponent({ __name: "GeolocateControls", props: { position: { default: "bottom-right" }, options: { default: () => ({}) }, debug: { type: Boolean, default: false }, autoCleanup: { type: Boolean, default: true }, onError: {}, onGeolocate: {}, onTrackingStart: {}, onTrackingEnd: {}, onOutOfMaxBounds: {} }, emits: ["register", "geolocate", "error", "outofmaxbounds", "trackuserlocationstart", "trackuserlocationend"], setup(__props, { expose: __expose, emit: __emit }) { const props = __props; const emits = __emit; const { logError } = useLogger(props.debug); const mapInstance = inject(MapProvideKey, ref(null)); const isControlRegistered = ref(false); const controlError = ref(null); const hasControlError = computed(() => !!controlError.value); const { geolocateControl, isControlAdded, removeControl, addControl, trigger } = useGeolocateControl({ map: mapInstance, position: props.position, options: props.options, debug: props.debug }); function handleGeolocateEvent(eventType, data) { var _a, _b, _c, _d, _e, _f; try { emits(eventType, data); switch (eventType) { case "geolocate": (_a = props.onGeolocate) == null ? void 0 : _a.call(props, data); break; case "error": controlError.value = data; (_b = props.onError) == null ? void 0 : _b.call(props, data); break; case "trackuserlocationstart": (_c = props.onTrackingStart) == null ? void 0 : _c.call(props, data); break; case "trackuserlocationend": (_d = props.onTrackingEnd) == null ? void 0 : _d.call(props, data); break; case "outofmaxbounds": (_e = props.onOutOfMaxBounds) == null ? void 0 : _e.call(props, data); break; default: break; } } catch (error) { logError(`Error handling ${eventType} event:`, error, { data }); controlError.value = error; (_f = props.onError) == null ? void 0 : _f.call(props, error); } } watchEffect(() => { var _a; try { if (geolocateControl.value && !isControlRegistered.value) { emits("register", geolocateControl.value); isControlRegistered.value = true; controlError.value = null; } } catch (error) { logError("Error registering geolocate control:", error); controlError.value = error; (_a = props.onError) == null ? void 0 : _a.call(props, error); } }); GeolocateEvents.map((evt) => { return useGeolocateEventListener({ geolocate: geolocateControl, event: evt, on: (data) => handleGeolocateEvent(evt, data), debug: props.debug }); }); function cleanup() { try { if (props.autoCleanup) { isControlRegistered.value = false; controlError.value = null; if (isControlAdded.value) { removeControl(); } } } catch (error) { logError("Error during geolocate control cleanup:", error); } } onUnmounted(cleanup); __expose({ geolocateControl, isControlAdded, isControlRegistered, hasControlError, controlError, addControl, removeControl, trigger, cleanup }); return (_ctx, _cache) => { return hasControlError.value ? (openBlock(), createElementBlock("div", _hoisted_1, [ renderSlot(_ctx.$slots, "error") ])) : createCommentVNode("", true); }; } }); const _sfc_main$7 = /* @__PURE__ */ defineComponent({ __name: "GeoJsonSource", props: { id: {}, data: { default: () => ({ type: "FeatureCollection", features: [] }) }, options: { default: () => ({}) }, register: {}, debug: { type: Boolean, default: false }, autoCleanup: { type: Boolean, default: true }, onError: {}, onLoad: {}, onDataUpdate: {}, debounceDelay: { default: 100 } }, emits: ["register", "error", "load", "data-update"], setup(__props, { expose: __expose, emit: __emit }) { const props = __props; const emits = __emit; const { logError } = useLogger(props.debug); const mapInstance = inject(MapProvideKey, ref(null)); const isSourceRegistered = ref(false); const lastDataUpdate = ref(); const isDataValid = computed(() => { const data = props.data; if (!data) return false; if (typeof data === "object" && "type" in data) { return data.type === "FeatureCollection" || data.type === "Feature"; } if (typeof data === "string") { try { new URL(data); return true; } catch { return false; } } return false; }); function handleSetData(newData) { var _a, _b; try { if (!newData) return; if (typeof newData === "object" && "type" in newData) { if (!["FeatureCollection", "Feature"].includes(newData.type)) { logError("Invalid GeoJSON type:", newData.type); return; } } setData(newData); lastDataUpdate.value = newData; emits("data-update", newData); (_a = props.onDataUpdate) == null ? void 0 : _a.call(props, newData); } catch (error) { logError("Error setting GeoJSON source data:", error); emits("error", error); (_b = props.onError) == null ? void 0 : _b.call(props, error); } } const { sourceId, getSource, setData, removeSource, refreshSource, sourceStatus, isSourceReady } = useCreateGeoJsonSource({ map: mapInstance, id: props.id, data: props.data, options: props.options, debug: props.debug, register: (actions) => { var _a, _b, _c; try { const enhancedActions = { ...actions, // Additional enhanced methods isSourceRegistered: isSourceRegistered.value, lastDataUpdate: lastDataUpdate.value, isDataValid: isDataValid.value }; (_a = props.register) == null ? void 0 : _a.call(props, enhancedActions); emits("register", enhancedActions); isSourceRegistered.value = true; if (actions.getSource.value) { emits("load", actions.getSource.value); (_b = props.onLoad) == null ? void 0 : _b.call(props, actions.getSource.value); } } catch (error) { logError("Error registering GeoJSON source:", error); emits("error", error); (_c = props.onError) == null ? void 0 : _c.call(props, error); } } }); provide(SourceProvideKey, getSource); const stopDataWatcher = useDebouncedWatch( () => props.data, (newData, oldData) => { var _a, _b; if (newData === oldData) return; try { if (newData && isDataValid.value) { handleSetData(newData); } else if (newData && !isDataValid.value) { const error = new Error("Invalid GeoJSON data format"); logError("Invalid GeoJSON data provided:", newData); emits("error", error); (_a = props.onError) == null ? void 0 : _a.call(props, error); } } catch (error) { logError("Error in data watcher:", error); emits("error", error); (_b = props.onError) == null ? void 0 : _b.call(props, error); } }, { delay: props.debounceDelay, deep: true, immediate: true, flush: "post", // Optimize by running after DOM updates debug: props.debug } ); function cleanup() { try { if (props.autoCleanup) { stopDataWatcher(); isSourceRegistered.value = false; lastDataUpdate.value = void 0; if (isSourceReady) { removeSource(); } } } catch (error) { logError("Error during GeoJSON source cleanup:", error); } } onUnmounted(cleanup); __expose({ sourceId, getSource, setData: handleSetData, removeSource, refreshSource, sourceStatus, isSourceReady, isSourceRegistered, isDataValid, lastDataUpdate, cleanup }); return (_ctx, _cache) => { return renderSlot(_ctx.$slots, "default"); }; } }); const _sfc_main$6 = /* @__PURE__ */ defineComponent({ __name: "FillLayer", props: { id: {}, filter: { type: [Boolean, Array] }, style: {}, maxzoom: {}, minzoom: {}, metadata: {}, source: {}, sourceLayer: {}, beforeId: {}, visible: { type: Boolean, default: true }, register: {} }, emits: ["register", "click", "dblclick", "mousedown", "mouseup", "mousemove", "mouseenter", "mouseleave", "mouseover", "mouseout", "contextmenu", "touchstart", "touchend", "touchcancel"], setup(__props, { emit: __emit }) { const props = __props; const emits = __emit; const sourceData = inject(SourceProvideKey, ref(null)); const mapInstance = inject(MapProvideKey, ref(null)); const effectiveSource = computed(() => props.source || sourceData.value); const visibilityStyle = computed( () => ({ visibility: props.visible ? "visible" : "none" }) ); const mergedStyle = computed(() => ({ ...props.style, ...visibilityStyle.value })); const handleRegister = (actions, map) => { emits("register", actions, map); }; const { getLayer, setBeforeId, setFilter, setStyle, setZoomRange, setLayoutProperty } = useCreateFillLayer({ map: mapInstance, source: effectiveSource, style: mergedStyle.value, filter: props.filter || ["all"], id: props.id, maxzoom: props.maxzoom, minzoom: props.minzoom, metadata: props.metadata, sourceLayer: props.sourceLayer, register: handleRegister }); MapboxLayerEvents.forEach((evt) => { useLayerEventListener({ map: mapInstance, layer: getLayer, event: evt, on: (data) => { emits(evt, data); } }); }); const stopPropsWatcher = watch( () => ({ filter: props.filter, style: props.style, maxzoom: props.maxzoom, minzoom: props.minzoom, beforeId: props.beforeId, visible: props.visible }), (newProps, oldProps) => { if (newProps.filter !== (oldProps == null ? void 0 : oldProps.filter)) { setFilter(newProps.filter); } if (newProps.style !== (oldProps == null ? void 0 : oldProps.style)) { setStyle(newProps.style); } if (newProps.maxzoom !== (oldProps == null ? void 0 : oldProps.maxzoom) || newProps.minzoom !== (oldProps == null ? void 0 : oldProps.minzoom)) { setZoomRange(newProps.minzoom, newProps.maxzoom); } if (newProps.beforeId !== (oldProps == null ? void 0 : oldProps.beforeId)) { setBeforeId(newProps.beforeId); } if (newProps.visible !== (oldProps == null ? void 0 : oldProps.visible)) { setLayoutProperty("visibility", newProps.visible ? "visible" : "none"); } }, { deep: true, flush: "post" // Run after DOM updates for better performance } ); onUnmounted(() => { stopPropsWatcher(); }); return (_ctx, _cache) => { return null; }; } }); const _sfc_main$5 = /* @__PURE__ */ defineComponent({ __name: "CircleLayer", props: { id: {}, filter: { type: [Boolean, Array], default: () => ["all"] }, style: { default: () => ({}) }, maxzoom: {}, minzoom: {}, metadata: {}, source: {}, sourceLayer: {}, beforeId: {}, visible: { type: Boolean, default: true }, debug: { type: Boolean, default: false }, register: {} }, emits: ["register", "click", "dblclick", "mousedown", "mouseup", "mousemove", "mouseenter", "mouseleave", "mouseover", "mouseout", "contextmenu", "touchstart", "touchend", "touchcancel"], setup(__props, { emit: __emit }) { const props = __props; const emits = __emit; const sourceData = inject(SourceProvideKey, ref(null)); const mapInstance = inject(MapProvideKey, ref(null)); const effectiveSource = computed(() => props.source || sourceData.value); const visibilityStyle = computed( () => ({ visibility: props.visible ? "visible" : "none" }) ); const mergedStyle = computed(() => ({ ...props.style, ...visibilityStyle.value })); const handleRegister = (actions, map) => { var _a; (_a = props.register) == null ? void 0 : _a.call(props, actions, map); emits("register", actions, map); }; const { getLayer, setBeforeId, setFilter, setStyle, setZoomRange, setLayoutProperty } = useCreateCircleLayer({ map: mapInstance, source: effectiveSource, style: mergedStyle.value, filter: props.filter || ["all"], id: props.id, maxzoom: props.maxzoom, minzoom: props.minzoom, metadata: props.metadata, sourceLayer: props.sourceLayer, register: handleRegister }); MapboxLayerEvents.forEach((evt) => { useLayerEventListener({ map: mapInstance, layer: getLayer, event: evt, on: (data) => { emits(evt, data); } }); }); const stopPropsWatcher = watch( () => ({ filter: props.filter, style: props.style, maxzoom: props.maxzoom, minzoom: props.minzoom, beforeId: props.beforeId, visible: props.visible }), (newProps, oldProps) => { if (newProps.filter !== (oldProps == null ? void 0 : oldProps.filter)) { setFilter(newProps.filter); } if (newProps.style !== (oldProps == null ? void 0 : oldProps.style)) { setStyle(newProps.style); } if (newProps.maxzoom !== (oldProps == null ? void 0 : oldProps.maxzoom) || newProps.minzoom !== (oldProps == null ? void 0 : oldProps.minzoom)) { setZoomRange(newProps.minzoom, newProps.maxzoom); } if (newProps.beforeId !== (oldProps == null ? void 0 : oldProps.beforeId)) { setBeforeId(newProps.beforeId); } if (newProps.visible !== (oldProps == null ? void 0 : oldProps.visible)) { setLayoutProperty("visibility", newProps.visible ? "visible" : "none"); } }, { deep: true, flush: "post" // Run after DOM updates for better performance } ); onUnmounted(() => { stopPropsWatcher(); }); return (_ctx, _cache) => { return null; }; } }); const _sfc_main$4 = /* @__PURE__ */ defineComponent({ __name: "LineLayer", props: { id: {}, filter: { type: [Boolean, Array] }, style: {}, maxzoom: {}, minzoom: {}, metadata: {}, source: {}, sourceLayer: {}, beforeId: {}, visible: { type: Boolean, default: true }, register: {} }, emits: ["register", "click", "dblclick", "mousedown", "mouseup", "mousemove", "mouseenter", "mouseleave", "mouseover", "mouseout", "contextmenu", "touchstart", "touchend", "touchcancel"], setup(__props, { emit: __emit }) { const props = __props; const emits = __emit; const sourceData = inject(SourceProvideKey, ref(null)); const mapInstance = inject(MapProvideKey, ref(null)); const effectiveSource = computed(() => props.source || sourceData.value); const visibilityStyle = computed( () => ({ visibility: props.visible ? "visible" : "none" }) ); const mergedStyle = computed(() => ({ ...props.style, ...visibilityStyle.value })); const handleRegister = (actions, map) => { var _a; (_a = props.register) == null ? void 0 : _a.call(props, actions, map); emits("register", actions, map); }; const { getLayer, setBeforeId, setFilter, setStyle, setZoomRange, setLayoutProperty } = useCreateLineLayer({ map: mapInstance, source: effectiveSource, style: mergedStyle.value, filter: props.filter || ["all"], id: props.id, maxzoom: props.maxzoom, minzoom: props.minzoom, metadata: props.metadata, sourceLayer: props.sourceLayer, register: handleRegister }); MapboxLayerEvents.forEach((evt) => { useLayerEventListener({ map: mapInstance, layer: getLayer, event: evt, on: (data) => { emits(evt, data); } }); }); const stopPropsWatcher = watch( () => ({ filter: props.filter, style: props.style, maxzoom: props.maxzoom, minzoom: props.minzoom, beforeId: props.beforeId, visible: props.visible }), (newProps, oldProps) => { if (newProps.filter !== (oldProps == null ? void 0 : oldProps.filter)) { setFilter(newProps.filter); } if (newProps.style !== (oldProps == null ? void 0 : oldProps.style)) { setStyle(newProps.style); } if (newProps.maxzoom !== (oldProps == null ? void 0 : oldProps.maxzoom) || newProps.minzoom !== (oldProps == null ? void 0 : oldProps.minzoom)) { setZoomRange(newProps.minzoom, newProps.maxzoom); } if (newProps.beforeId !== (oldProps == null ? void 0 : oldProps.beforeId)) { setBeforeId(newProps.beforeId); } if (newProps.visible !== (oldProps == null ? void 0 : oldProps.visible)) { setLayoutProperty("visibility", newProps.visible ? "visible" : "none"); } }, { deep: true, flush: "post" // Run after DOM updates for better performance } ); onUnmounted(() => { stopPropsWatcher(); }); return (_ctx, _cache) => { return null; }; } }); const _sfc_main$3 = /* @__PURE__ */ defineComponent({ __name: "SymbolLayer", props: { id: {}, filter: { type: [Boolean, Array] }, style: {}, maxzoom: {}, minzoom: {}, metadata: {}, source: {}, sourceLayer: {}, beforeId: {}, visible: { type: Boolean, default: true }, register: {} }, emits: ["register", "click", "dblclick", "mousedown", "mouseup", "mousemove", "mouseenter", "mouseleave", "mouseover", "mouseout", "contextmenu", "touchstart", "touchend", "touchcancel"], setup(__props, { emit: __emit }) { const props = __props; const emits = __emit; const sourceData = inject(SourceProvideKey, ref(null)); const mapInstance = inject(MapProvideKey, ref(null)); const effectiveSource = computed(() => props.source || sourceData.value); const visibilityStyle = computed( () => ({ visibility: props.visible ? "visible" : "none" }) ); const mergedStyle = computed(() => ({ ...props.style, ...visibilityStyle.value })); const handleRegister = (actions, map) => { var _a; (_a = props.register) == null ? void 0 : _a.call(props, actions, map); emits("register", actions, map); }; const { getLayer, setBeforeId, setFilter, setStyle, setZoomRange, setLayoutProperty } = useCreateSymbolLayer({ map: mapInstance, source: effectiveSource, style: mergedStyle.value, filter: props.filter || ["all"], id: props.id, maxzoom: props.maxzoom, minzoom: props.minzoom, metadata: props.metadata, sourceLayer: props.sourceLayer, register: handleRegister }); MapboxLayerEvents.forEach((evt) => { useLayerEventListener({ map: mapInstance, layer: getLayer, event: evt, on: (data) => { emits(evt, data); } }); }); const stopPropsWatcher = watch( () => ({ filter: props.filter, style: props.style, maxzoom: props.maxzoom, minzoom: props.minzoom, beforeId: props.beforeId, visible: props.visible }), (newProps, oldProps) => { if (newProps.filter !== (oldProps == null ? void 0 : oldProps.filter)) { setFilter(newProps.filter); } if (newProps.style !== (oldProps == null ? void 0 : oldProps.style)) { setStyle(newProps.style); } if (newProps.maxzoom !== (oldProps == null ? void 0 : oldProps.maxzoom) || newProps.minzoom !== (oldProps == null ? void 0 : oldProps.minzoom)) { setZoomRange(newProps.minzoom, newProps.maxzoom); } if (newProps.beforeId !== (oldProps == null ? void 0 : oldProps.beforeId)) { setBeforeId(newProps.beforeId); } if (newProps.visible !== (oldProps == null ? void 0 : oldProps.visible)) { setLayoutProperty("visibility", newProps.visible ? "visible" : "none"); } }, { deep: true, flush: "post" // Run after DOM updates for better performance } ); onUnmounted(() => { stopPropsWatcher(); }); return (_ctx, _cache) => { return null; }; } }); const _sfc_main$2 = /* @__PURE__ */ defineComponent({ __name: "Image", props: { images: { default: () => [] }, options: {}, showLoading: { type: Boolean, default: true }, debug: { type: Boolean }, forceRecreateOnDimensionChange: { type: Boolean, default: true } }, setup(__props) { const props = __props; const { logError } = useLogger(props.debug); const loading = ref(true); const mapInstance = inject(MapProvideKey, ref(null)); const hasImages = computed(() => props.images.length > 0); async function loadImages(images) { if (!images.length) { loading.value = false; return; } loading.value = true; try { const loadPromises = images.map(async (image) => { try { const actions = useCreateImage({ map: mapInstance, id: image.id, image: image.image, options: image.options || props.options, debug: props.debug, forceRecreateOnDimensionChange: props.forceRecreateOnDimensionChange }); await actions.loadPromise; } catch (error) { const errorMessage = `Failed to load image ${image.id}: ${error}`; logError(errorMessage); } }); await Promise.allSettled(loadPromises); } catch (error) { logError("Error loading images:", error); } finally { loading.value = false; } } watch( () => props.images, (newImages) => { if (newImages.length > 0) { loadImages(newImages); } }, { deep: true, immediate: false } ); onMounted(() => { if (hasImages.value) { loadImages(props.images); } else { loading.value = false; } }); return (_ctx, _cache) => { return !loading.value ? renderSlot(_ctx.$slots, "default", { key: 0 }) : createCommentVNode("", true); }; } }); const _sfc_main$1 = /* @__PURE__ */ defineComponent({ __name: "PopUp", props: { className: {}, lnglat: {}, show: { type: Boolean, default: true }, withMap: { type: Boolean, default: true }, options: {}, html: {}, maxWidth: {}, closeButton: { type: Boolean, default: true }, closeOnClick: { type: Boolean, default: true }, closeOnEscape: { type: Boolean, default: true } }, emits: ["close", "open", "update:show"], setup(__props, { emit: __emit }) { const props = __props; const emits = __emit; const mapInstance = inject(MapProvideKey, ref(null)); const popupElRef = ref(); const popupOptions = computed(() => ({ ...props.options, className: props.className, maxWidth: props.maxWidth, closeButton: props.closeButton, closeOnClick: props.closeOnClick, closeOnEscape: props.closeOnEscape })); const eventHandlers = { open: () => { emits("open"); emits("update:show", true); }, close: () => { emits("close"); emits("update:show", false); } }; const { setLngLat, show, hide } = useCreatePopup({ map: mapInstance, el: popupElRef, lnglat: props.lnglat, html: props.html, show: props.show, withMap: props.withMap, options: popupOptions.value, on: eventHandlers }); watch( () => props.show, (isShow) => { isShow ? show() : hide(); } ); watch( () => props.lnglat, (newLnglat) => { if (newLnglat) { setLngLat(newLnglat); } }, { deep: true } ); return (_ctx, _cache) => { return openBlock(), createElementBlock("div", { ref_key: "popupElRef", ref: popupElRef, class: "mapboxgl-popup-content-inner" }, [ renderSlot(_ctx.$slots, "default") ], 512); }; } }); const _sfc_main = /* @__PURE__ */ defineComponent({ __name: "Marker", props: { lnglat: {}, popup: {}, options: { default: () => ({}) }, draggable: { type: Boolean }, element: {}, offset: {}, anchor: {}, color: {}, clickTolerance: {}, rotation: {}, rotationAlignment: {}, pitchAlignment: {}, scale: {}, occludedOpacity: {} }, emits: ["dragstart", "drag", "dragend"], setup(__props, { emit: __emit }) { const props = __props; const emits = __emit; const slots = useSlots(); const mapInstance = inject(MapProvideKey, ref(null)); const markerElRef = ref(); const hasCustomElement = computed(() => { var _a; return Boolean((_a = slots.default) == null ? void 0 : _a.call(slots)); }); const markerOptions = computed(() => ({ ...props.options, ...props.draggable !== void 0 && { draggable: props.draggable }, ...props.offset !== void 0 && { offset: props.offset }, ...props.anchor !== void 0 && { anchor: props.anchor }, ...props.color !== void 0 && { color: props.color }, ...props.clickTolerance !== void 0 && { clickTolerance: props.clickTolerance }, ...props.rotation !== void 0 && { rotation: props.rotation }, ...props.rotationAlignment !== void 0 && { rotationAlignment: props.rotationAlignment }, ...props.pitchAlignment !== void 0 && { pitchAlignment: props.pitchAlignment }, ...props.scale !== void 0 && { scale: props.scale }, ...props.occludedOpacity !== void 0 && { occludedOpacity: props.occludedOpacity } })); const eventHandlers = { dragstart: (ev) => { emits("dragstart", ev); }, drag: (ev) => { emits("drag", ev); }, dragend: (ev) => { emits("dragend", ev); } }; const { setDraggable, setLngLat } = useCreateMarker({ map: mapInstance, el: hasCustomElement.value ? markerElRef : void 0, lnglat: props.lnglat, popup: props.popup, options: markerOptions.value, on: eventHandlers }); watch( () => props.lnglat, (newLnglat) => { if (newLnglat) { setLngLat(newLnglat); } }, { deep: true } ); watch( () => props.draggable, (newDraggable) => { if (newDraggable !== void 0) { setDraggable(newDraggable); } } ); return (_ctx, _cache) => { return openBlock(), createElementBlock("div", { ref_key: "markerElRef", ref: markerElRef }, [ renderSlot(_ctx.$slots, "default") ], 512); }; } }); export { GeolocateEvents as G, MapCreationStatus as M, SourceProvideKey as S, _sfc_main$9 as _, MapProvideKey as a, MapboxEvents as b, MapboxLayerEvents as c, _sfc_main$8 as d, _sfc_main$7 as e, _sfc_main$6 as f, _sfc_main$5 as g, _sfc_main$4 as h, _sfc_main$3 as i, _sfc_main$2 as j, _sfc_main$1 as k, _sfc_main as l }; //# sourceMappingURL=components-DEq_E09C.js.map