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
JavaScript
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