UNPKG

maplair

Version:

JavaScript library for mobile-friendly interactive maps

6,704 lines • 220 kB
/* @preserve
 * Maplair 4.0.0-alpha.1, a JS library for interactive maps. https://maplair.org
 * (c) 2026 Maplair contributors, (c) 2010-2026 Volodymyr Agafonkin, (c) 2010-2011 CloudMade
 */

//#region \0rolldown/runtime.js
var __defProp = Object.defineProperty;
var __exportAll = (all, no_symbols) => {
	let target = {};
	for (var name in all) __defProp(target, name, {
		get: all[name],
		enumerable: true
	});
	if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
	return target;
};
//#endregion
//#region package.json
var version$1 = "4.0.0-alpha.1";
//#endregion
//#region src/core/Util.js
var Util_exports = /* @__PURE__ */ __exportAll({
	falseFn: () => falseFn,
	formatNum: () => formatNum,
	lastId: () => lastId,
	setOptions: () => setOptions,
	splitWords: () => splitWords,
	stamp: () => stamp,
	template: () => template,
	throttle: () => throttle,
	wrapNum: () => wrapNum
});
let lastId = 0;
function stamp(obj) {
	if (!("_maplair_id" in obj)) obj["_maplair_id"] = ++lastId;
	return obj._maplair_id;
}
function throttle(fn, time, context) {
	let lock, queuedArgs;
	function later() {
		lock = false;
		if (queuedArgs) {
			wrapperFn.apply(context, queuedArgs);
			queuedArgs = false;
		}
	}
	function wrapperFn(...args) {
		if (lock) queuedArgs = args;
		else {
			fn.apply(context, args);
			setTimeout(later, time);
			lock = true;
		}
	}
	return wrapperFn;
}
function wrapNum(x, range, includeMax) {
	const max = range[1], min = range[0], d = max - min;
	return x === max && includeMax ? x : ((x - min) % d + d) % d + min;
}
function falseFn() {
	return false;
}
function formatNum(num, precision) {
	if (precision === false) return num;
	const pow = 10 ** (precision === void 0 ? 6 : precision);
	return Math.round(num * pow) / pow;
}
const WHITESPACE_RE = /\s+/;
function splitWords(str) {
	return str.trim().split(WHITESPACE_RE);
}
function setOptions(obj, options) {
	if (!Object.hasOwn(obj, "options")) obj.options = obj.options ? Object.create(obj.options) : {};
	for (const i in options) if (Object.hasOwn(options, i)) obj.options[i] = options[i];
	return obj.options;
}
const templateRe = /\{ *([\w_ -]+) *\}/g;
function template(str, data) {
	return str.replace(templateRe, (str, key) => {
		let value = data[key];
		if (value === void 0) throw new Error(`No value provided for variable ${str}`);
		else if (typeof value === "function") value = value(data);
		return value;
	});
}
//#endregion
//#region src/core/Class.js
var Class = class {
	static include(props) {
		const parentOptions = this.prototype.options;
		for (const k of getAllMethodNames(props)) this.prototype[k] = props[k];
		if (props.options) {
			this.prototype.options = parentOptions;
			this.mergeOptions(props.options);
		}
		return this;
		function* getAllMethodNames(obj) {
			do {
				if (obj === Object || obj === Object.prototype) break;
				for (const k of Object.getOwnPropertyNames(obj)) yield k;
			} while ((obj = Object.getPrototypeOf(obj)) !== void 0);
		}
	}
	static setDefaultOptions(options) {
		setOptions(this.prototype, options);
		return this;
	}
	static mergeOptions(options) {
		this.prototype.options ??= {};
		Object.assign(this.prototype.options, options);
		return this;
	}
	static addInitHook(fn, ...args) {
		const init = typeof fn === "function" ? fn : function() {
			this[fn](...args);
		};
		if (!Object.hasOwn(this, "_initHooks")) this._initHooks = [];
		this._initHooks.push(init);
		return this;
	}
	constructor() {
		setOptions(this);
	}
	callInitHooks(cls = this.constructor) {
		const done = this._initHooksCalledFor;
		if (done && (done === cls || done.prototype instanceof cls)) return this;
		const classes = [];
		for (let c = cls; c && c !== Function.prototype && c !== done; c = Object.getPrototypeOf(c)) classes.unshift(c);
		this._initHooksCalledFor = cls;
		for (const c of classes) if (Object.hasOwn(c, "_initHooks")) for (const hook of c._initHooks) hook.call(this);
		return this;
	}
};
//#endregion
//#region src/geometry/Point.js
var Point = class Point {
	constructor(x, y, round) {
		if (!Point.validate(x, y)) throw new Error(`Invalid Point object: (${x}, ${y})`);
		let _x, _y;
		if (x instanceof Point) {
			_x = x.x;
			_y = x.y;
		} else if (Array.isArray(x)) {
			_x = x[0];
			_y = x[1];
		} else if (typeof x === "object" && "x" in x && "y" in x) {
			_x = x.x;
			_y = x.y;
		} else {
			_x = x;
			_y = y;
		}
		this.x = round ? Math.round(_x) : _x;
		this.y = round ? Math.round(_y) : _y;
	}
	static validate(x, y) {
		if (x instanceof Point || Array.isArray(x)) return true;
		else if (x && typeof x === "object" && "x" in x && "y" in x) return true;
		else if ((x || x === 0) && (y || y === 0)) return true;
		return false;
	}
	add(point) {
		return new Point(this)._add(new Point(point));
	}
	_add(point) {
		this.x += point.x;
		this.y += point.y;
		return this;
	}
	subtract(point) {
		return new Point(this)._subtract(new Point(point));
	}
	_subtract(point) {
		this.x -= point.x;
		this.y -= point.y;
		return this;
	}
	divideBy(num) {
		return new Point(this)._divideBy(num);
	}
	_divideBy(num) {
		this.x /= num;
		this.y /= num;
		return this;
	}
	multiplyBy(num) {
		return new Point(this)._multiplyBy(num);
	}
	_multiplyBy(num) {
		this.x *= num;
		this.y *= num;
		return this;
	}
	scaleBy(point) {
		return new Point(this.x * point.x, this.y * point.y);
	}
	unscaleBy(point) {
		return new Point(this.x / point.x, this.y / point.y);
	}
	round() {
		return new Point(this)._round();
	}
	_round() {
		this.x = Math.round(this.x);
		this.y = Math.round(this.y);
		return this;
	}
	floor() {
		return new Point(this)._floor();
	}
	_floor() {
		this.x = Math.floor(this.x);
		this.y = Math.floor(this.y);
		return this;
	}
	ceil() {
		return new Point(this)._ceil();
	}
	_ceil() {
		this.x = Math.ceil(this.x);
		this.y = Math.ceil(this.y);
		return this;
	}
	trunc() {
		return new Point(this)._trunc();
	}
	_trunc() {
		this.x = Math.trunc(this.x);
		this.y = Math.trunc(this.y);
		return this;
	}
	distanceTo(point) {
		point = new Point(point);
		const x = point.x - this.x, y = point.y - this.y;
		return Math.sqrt(x * x + y * y);
	}
	equals(point) {
		point = new Point(point);
		return point.x === this.x && point.y === this.y;
	}
	contains(point) {
		point = new Point(point);
		return Math.abs(point.x) <= Math.abs(this.x) && Math.abs(point.y) <= Math.abs(this.y);
	}
	toString() {
		return `Point(${formatNum(this.x)}, ${formatNum(this.y)})`;
	}
};
//#endregion
//#region src/core/Browser.js
const chrome = userAgentContains("chrome");
const safari = !chrome && userAgentContains("safari");
const mobile = typeof orientation !== "undefined";
const reducedMotion = navigator.preferences?.reducedMotion?.value ? navigator.preferences.reducedMotion.value === "reduce" : typeof window === "undefined" ? true : window?.matchMedia("(prefers-reduced-motion: reduce)").matches;
const pointer = typeof window === "undefined" ? false : !!window.PointerEvent;
const touchNative = typeof window === "undefined" ? false : "ontouchstart" in window || !!window.TouchEvent;
const touch = touchNative || pointer;
const retina = typeof window === "undefined" || typeof window.devicePixelRatio === "undefined" ? false : window.devicePixelRatio > 1;
const mac = typeof navigator === "undefined" || typeof navigator.platform === "undefined" ? false : navigator.platform.startsWith("Mac");
const linux = typeof navigator === "undefined" || typeof navigator.platform === "undefined" ? false : navigator.platform.startsWith("Linux");
function userAgentContains(str) {
	if (typeof navigator === "undefined" || typeof navigator.userAgent === "undefined") return false;
	return navigator.userAgent.toLowerCase().includes(str);
}
var Browser_default = {
	chrome,
	safari,
	mobile,
	reducedMotion,
	pointer,
	touch,
	touchNative,
	retina,
	mac,
	linux
};
//#endregion
//#region src/dom/DomEvent.DoubleTap.js
function makeDblclick(ev) {
	let init = {
		bubbles: ev.bubbles,
		cancelable: ev.cancelable,
		composed: ev.composed,
		detail: 2,
		view: ev.view,
		screenX: ev.screenX,
		screenY: ev.screenY,
		clientX: ev.clientX,
		clientY: ev.clientY,
		ctrlKey: ev.ctrlKey,
		shiftKey: ev.shiftKey,
		altKey: ev.altKey,
		metaKey: ev.metaKey,
		button: ev.button,
		buttons: ev.buttons,
		relatedTarget: ev.relatedTarget,
		region: ev.region
	};
	let newEvent;
	if (ev instanceof PointerEvent) {
		init = {
			...init,
			pointerId: ev.pointerId,
			width: ev.width,
			height: ev.height,
			pressure: ev.pressure,
			tangentialPressure: ev.tangentialPressure,
			tiltX: ev.tiltX,
			tiltY: ev.tiltY,
			twist: ev.twist,
			pointerType: ev.pointerType,
			isPrimary: ev.isPrimary
		};
		newEvent = new PointerEvent("dblclick", init);
	} else newEvent = new MouseEvent("dblclick", init);
	return newEvent;
}
const delay = 200;
function addDoubleTapListener(obj, handler) {
	obj.addEventListener("dblclick", handler);
	let last = 0, detail;
	function simDblclick(ev) {
		if (ev.detail !== 1) {
			detail = ev.detail;
			return;
		}
		if (ev.pointerType === "mouse" || ev.sourceCapabilities && !ev.sourceCapabilities.firesTouchEvents) return;
		const path = getPropagationPath(ev);
		if (path.some((el) => el instanceof HTMLLabelElement && el.attributes.for) && !path.some((el) => el instanceof HTMLInputElement || el instanceof HTMLSelectElement)) return;
		const now = Date.now();
		if (now - last <= delay) {
			detail++;
			if (detail === 2) ev.target.dispatchEvent(makeDblclick(ev));
		} else detail = 1;
		last = now;
	}
	obj.addEventListener("click", simDblclick);
	return {
		dblclick: handler,
		simDblclick
	};
}
function removeDoubleTapListener(obj, handlers) {
	obj.removeEventListener("dblclick", handlers.dblclick);
	obj.removeEventListener("click", handlers.simDblclick);
}
//#endregion
//#region src/dom/DomEvent.PointerEvents.js
var DomEvent_PointerEvents_exports = /* @__PURE__ */ __exportAll({
	cleanupPointers: () => cleanupPointers,
	disablePointerDetection: () => disablePointerDetection,
	enablePointerDetection: () => enablePointerDetection,
	getPointers: () => getPointers
});
const activePointers = /* @__PURE__ */ new Map();
function enablePointerDetection(el) {
	el.addEventListener("pointerdown", _onSet, { capture: true });
	el.addEventListener("pointermove", _onUpdate, { capture: true });
	el.addEventListener("pointerup", _onDelete, { capture: true });
	el.addEventListener("pointercancel", _onDelete, { capture: true });
	activePointers.clear();
}
function disablePointerDetection(el) {
	el.removeEventListener("pointerdown", _onSet, { capture: true });
	el.removeEventListener("pointermove", _onUpdate, { capture: true });
	el.removeEventListener("pointerup", _onDelete, { capture: true });
	el.removeEventListener("pointercancel", _onDelete, { capture: true });
}
function _onSet(e) {
	e.target.setPointerCapture(e.pointerId);
	activePointers.set(e.pointerId, e);
}
function _onUpdate(e) {
	if (activePointers.has(e.pointerId)) activePointers.set(e.pointerId, e);
}
function _onDelete(e) {
	e.target.releasePointerCapture(e.pointerId);
	activePointers.delete(e.pointerId);
}
function getPointers() {
	return [...activePointers.values()];
}
function cleanupPointers() {
	for (const e of activePointers.values()) try {
		e.target.releasePointerCapture(e.pointerId);
	} catch {}
	activePointers.clear();
}
//#endregion
//#region src/dom/DomEvent.js
var DomEvent_exports = /* @__PURE__ */ __exportAll({
	PointerEvents: () => DomEvent_PointerEvents_exports,
	disableClickPropagation: () => disableClickPropagation,
	disableScrollPropagation: () => disableScrollPropagation,
	getPointerPosition: () => getPointerPosition,
	getPropagationPath: () => getPropagationPath,
	getWheelDelta: () => getWheelDelta,
	getWheelPxFactor: () => getWheelPxFactor,
	isExternalTarget: () => isExternalTarget,
	off: () => off,
	on: () => on,
	preventDefault: () => preventDefault,
	stop: () => stop,
	stopPropagation: () => stopPropagation
});
function on(obj, types, fn, context) {
	if (types && typeof types === "object") for (const [type, listener] of Object.entries(types)) addOne(obj, type, listener, fn);
	else for (const type of splitWords(types)) addOne(obj, type, fn, context);
	return this;
}
const eventsKey = "_maplair_events";
function off(obj, types, fn, context) {
	if (arguments.length === 1) {
		batchRemove(obj);
		delete obj[eventsKey];
	} else if (types && typeof types === "object") for (const [type, listener] of Object.entries(types)) removeOne(obj, type, listener, fn);
	else {
		types = splitWords(types);
		if (arguments.length === 2) batchRemove(obj, (type) => types.includes(type));
		else for (const type of types) removeOne(obj, type, fn, context);
	}
	return this;
}
const DIGIT_RE = /\d/;
function batchRemove(obj, filterFn) {
	for (const id of Object.keys(obj[eventsKey] ?? {})) {
		const type = id.split(DIGIT_RE)[0];
		if (!filterFn || filterFn(type)) removeOne(obj, type, null, null, id);
	}
}
const pointerSubst = {
	pointerenter: "pointerover",
	pointerleave: "pointerout",
	wheel: typeof window === "undefined" ? false : !("onwheel" in window) && "mousewheel"
};
function addOne(obj, type, fn, context) {
	const id = type + stamp(fn) + (context ? `_${stamp(context)}` : "");
	if (obj[eventsKey] && obj[eventsKey][id]) return this;
	let handler = function(e) {
		return fn.call(context || obj, e);
	};
	const originalHandler = handler;
	if (Browser_default.touch && type === "dblclick") handler = addDoubleTapListener(obj, handler);
	else if ("addEventListener" in obj) {
		if (type === "wheel" || type === "mousewheel") obj.addEventListener(pointerSubst[type] || type, handler, { passive: false });
		else if (type === "pointerenter" || type === "pointerleave") {
			handler = function(e) {
				if (isExternalTarget(obj, e)) originalHandler(e);
			};
			obj.addEventListener(pointerSubst[type], handler, false);
		} else obj.addEventListener(type, originalHandler, false);
	} else obj.attachEvent(`on${type}`, handler);
	obj[eventsKey] ??= {};
	obj[eventsKey][id] = handler;
}
function removeOne(obj, type, fn, context, id) {
	id ??= type + stamp(fn) + (context ? `_${stamp(context)}` : "");
	const handler = obj[eventsKey] && obj[eventsKey][id];
	if (!handler) return this;
	if (Browser_default.touch && type === "dblclick") removeDoubleTapListener(obj, handler);
	else if ("removeEventListener" in obj) obj.removeEventListener(pointerSubst[type] || type, handler, false);
	else obj.detachEvent(`on${type}`, handler);
	obj[eventsKey][id] = null;
}
function stopPropagation(e) {
	if (e.stopPropagation) e.stopPropagation();
	else if (e.originalEvent) e.originalEvent._stopped = true;
	else console.debug("Unsupported event", e);
	return this;
}
function disableScrollPropagation(el) {
	addOne(el, "wheel", stopPropagation);
	return this;
}
function disableClickPropagation(el) {
	on(el, "pointerdown dblclick contextmenu", stopPropagation);
	el["_maplair_disable_click"] = true;
	return this;
}
function preventDefault(e) {
	e.preventDefault?.();
	return this;
}
function stop(e) {
	preventDefault(e);
	stopPropagation(e);
	return this;
}
function getPropagationPath(ev) {
	return ev.composedPath();
}
function getPointerPosition(e, container) {
	if (!container) return new Point(e.clientX, e.clientY);
	const scale = getScale(container), offset = scale.boundingClientRect;
	return new Point((e.clientX - offset.left) / scale.x - container.clientLeft, (e.clientY - offset.top) / scale.y - container.clientTop);
}
function getWheelPxFactor() {
	const ratio = window.devicePixelRatio;
	return Browser_default.linux && Browser_default.chrome ? ratio : Browser_default.mac ? ratio * 3 : ratio > 0 ? 2 * ratio : 1;
}
function getWheelDelta(e) {
	return e.deltaY && e.deltaMode === 0 ? -e.deltaY / getWheelPxFactor() : e.deltaY && e.deltaMode === 1 ? -e.deltaY * 20 : e.deltaY && e.deltaMode === 2 ? -e.deltaY * 60 : e.deltaX || e.deltaZ ? 0 : 0;
}
function isExternalTarget(el, e) {
	let related = e.relatedTarget;
	if (!related) return true;
	try {
		while (related && related !== el) related = related.parentNode;
	} catch (err) {
		return false;
	}
	return related !== el;
}
//#endregion
//#region src/dom/DomUtil.js
var DomUtil_exports = /* @__PURE__ */ __exportAll({
	create: () => create,
	disableImageDrag: () => disableImageDrag,
	disableTextSelection: () => disableTextSelection,
	enableImageDrag: () => enableImageDrag,
	enableTextSelection: () => enableTextSelection,
	get: () => get,
	getPosition: () => getPosition,
	getScale: () => getScale,
	getSizedParentNode: () => getSizedParentNode,
	preventOutline: () => preventOutline,
	restoreOutline: () => restoreOutline,
	setPosition: () => setPosition,
	setTransform: () => setTransform,
	toBack: () => toBack,
	toFront: () => toFront
});
function get(id) {
	return typeof id === "string" ? document.getElementById(id) : id;
}
function create(tagName, className, container) {
	const el = document.createElement(tagName);
	el.className = className ?? "";
	container?.appendChild(el);
	return el;
}
function toFront(el) {
	const parent = el.parentNode;
	if (parent && parent.lastChild !== el) parent.appendChild(el);
}
function toBack(el) {
	const parent = el.parentNode;
	if (parent && parent.firstChild !== el) parent.insertBefore(el, parent.firstChild);
}
function setTransform(el, offset, scale) {
	const pos = offset ?? new Point(0, 0);
	const transform = `translate3d(${pos.x}px, ${pos.y}px, 0px)${scale ? ` scale(${scale})` : ""}`;
	if (el.style.transform !== transform) el.style.transform = transform;
}
const positions = /* @__PURE__ */ new WeakMap();
function setPosition(el, point) {
	positions.set(el, point);
	setTransform(el, point);
}
function getPosition(el) {
	return positions.get(el) ?? new Point(0, 0);
}
const documentStyle = typeof document === "undefined" ? {} : document.documentElement.style;
const userSelectProp = ["userSelect", "WebkitUserSelect"].find((prop) => prop in documentStyle);
let prevUserSelect;
function disableTextSelection() {
	const value = documentStyle[userSelectProp];
	if (value === "none") return;
	prevUserSelect = value;
	documentStyle[userSelectProp] = "none";
}
function enableTextSelection() {
	if (typeof prevUserSelect === "undefined") return;
	documentStyle[userSelectProp] = prevUserSelect;
	prevUserSelect = void 0;
}
function disableImageDrag() {
	on(window, "dragstart", preventDefault);
}
function enableImageDrag() {
	off(window, "dragstart", preventDefault);
}
let _outlineElement;
let _outlineStyle;
function preventOutline(element) {
	while (element.tabIndex === -1) element = element.parentNode;
	if (!element.style) return;
	restoreOutline();
	_outlineElement = element;
	_outlineStyle = element.style.outlineStyle;
	element.style.outlineStyle = "none";
	on(window, "keydown", restoreOutline);
}
function restoreOutline() {
	if (!_outlineElement) return;
	_outlineElement.style.outlineStyle = _outlineStyle;
	_outlineElement = void 0;
	_outlineStyle = void 0;
	off(window, "keydown", restoreOutline);
}
function getSizedParentNode(element) {
	do
		element = element.parentNode;
	while ((!element.offsetWidth || !element.offsetHeight) && element !== document.body);
	return element;
}
function getScale(element) {
	const rect = element.getBoundingClientRect();
	return {
		x: rect.width / element.offsetWidth || 1,
		y: rect.height / element.offsetHeight || 1,
		boundingClientRect: rect
	};
}
//#endregion
//#region src/control/Control.js
var Control = class Control extends Class {
	static {
		this.setDefaultOptions({ position: "topright" });
	}
	constructor(options) {
		super();
		setOptions(this, options);
		this.callInitHooks(Control);
	}
	getPosition() {
		return this.options.position;
	}
	setPosition(position) {
		const map = this._map;
		map?.removeControl(this);
		this.options.position = position;
		map?.addControl(this);
		return this;
	}
	getContainer() {
		return this._container;
	}
	addTo(map) {
		this.remove();
		this._map = map;
		const container = this._container = this.onAdd(map), pos = this.getPosition(), corner = map._controlCorners[pos];
		container.classList.add("maplair-control");
		if (pos.includes("bottom")) corner.insertBefore(container, corner.firstChild);
		else corner.appendChild(container);
		this._map.on("unload", this.remove, this);
		return this;
	}
	remove() {
		if (!this._map) return this;
		this._container.remove();
		if (this.onRemove) this.onRemove(this._map);
		this._map.off("unload", this.remove, this);
		this._map = null;
		return this;
	}
	_refocusOnMap(e) {
		if (this._map && e && !(e.screenX === 0 && e.screenY === 0)) this._map.getContainer().focus();
	}
	static register(MaplairMap) {
		MaplairMap.include({
			addControl(control) {
				control.addTo(this);
				return this;
			},
			removeControl(control) {
				control.remove();
				return this;
			},
			_initControlPos() {
				const corners = this._controlCorners = {}, l = "maplair-", container = this._controlContainer = create("div", `${l}control-container`, this._container);
				function createCorner(vSide, hSide) {
					const className = `${l + vSide} ${l}${hSide}`;
					corners[vSide + hSide] = create("div", className, container);
				}
				createCorner("top", "left");
				createCorner("top", "right");
				createCorner("bottom", "left");
				createCorner("bottom", "right");
			},
			_clearControlPos() {
				for (const c of Object.values(this._controlCorners)) c.remove();
				this._controlContainer.remove();
				delete this._controlCorners;
				delete this._controlContainer;
			}
		});
	}
};
//#endregion
//#region src/core/I18n.js
var I18n = class {
	static #messages = {};
	static #locale = null;
	static registerLocale(locale, messages) {
		this.#messages[locale] = {
			...this.#messages[locale],
			...messages
		};
	}
	static setLocale(locale) {
		this.#locale = locale;
	}
	static getLocale() {
		return this.#locale;
	}
	static translate(string, data = {}) {
		if (this.#locale === null) return template(string, data);
		const translation = this.#messages[this.#locale]?.[string];
		if (!translation) {
			console.warn(`No translation found for "${string}", falling back to the original string.`);
			return template(string, data);
		}
		try {
			return template(translation, data);
		} catch (err) {
			console.error(`Error while translating "${translation}".`, err);
			return translation;
		}
	}
};
//#endregion
//#region src/control/AttributionControl.js
const mapleLeaf = "<span aria-hidden=\"true\" class=\"maplair-attribution-leaf\">&#x1F341;</span>";
var AttributionControl = class AttributionControl extends Control {
	static {
		this.setDefaultOptions({
			position: "bottomright",
			prefix: null
		});
	}
	constructor(options) {
		super(options);
		if (this.options.prefix === null) {
			const title = I18n.translate("A JavaScript library for interactive maps");
			this.options.prefix = `<a target="_blank" href="https://maplair.org" title="${title}">${mapleLeaf}Maplair</a>`;
		}
		this._attributions = {};
		this.callInitHooks(AttributionControl);
	}
	onAdd(map) {
		map.attributionControl = this;
		this._container = create("div", "maplair-control-attribution");
		disableClickPropagation(this._container);
		for (const layer of Object.values(map._layers)) if (layer.getAttribution) this.addAttribution(layer.getAttribution());
		this._update();
		map.on("layeradd", this._addAttribution, this);
		return this._container;
	}
	onRemove(map) {
		map.off("layeradd", this._addAttribution, this);
	}
	_addAttribution(ev) {
		if (ev.layer.getAttribution) {
			this.addAttribution(ev.layer.getAttribution());
			ev.layer.once("remove", () => this.removeAttribution(ev.layer.getAttribution()));
		}
	}
	setPrefix(prefix) {
		this.options.prefix = prefix;
		this._update();
		return this;
	}
	addAttribution(text) {
		if (!text) return this;
		if (!this._attributions[text]) this._attributions[text] = 0;
		this._attributions[text]++;
		this._update();
		return this;
	}
	removeAttribution(text) {
		if (!text) return this;
		if (this._attributions[text]) {
			this._attributions[text]--;
			this._update();
		}
		return this;
	}
	_update() {
		if (!this._map) return;
		const attribs = Object.keys(this._attributions).filter((i) => this._attributions[i]);
		const prefixAndAttribs = [];
		if (this.options.prefix) prefixAndAttribs.push(this.options.prefix);
		if (attribs.length) prefixAndAttribs.push(attribs.join(", "));
		this._container.innerHTML = prefixAndAttribs.join(" <span aria-hidden=\"true\">|</span> ");
	}
	static register(MaplairMap) {
		MaplairMap.mergeOptions({ attributionControl: true });
		MaplairMap.addInitHook(function() {
			if (this.options.attributionControl) new AttributionControl().addTo(this);
		});
	}
};
//#endregion
//#region src/control/LayersControl.js
var LayersControl = class LayersControl extends Control {
	static {
		this.setDefaultOptions({
			collapsed: true,
			collapseDelay: 0,
			position: "topright",
			autoZIndex: true,
			hideSingleBase: false,
			sortLayers: false,
			sortFunction(layerA, layerB, nameA, nameB) {
				return nameA < nameB ? -1 : nameB < nameA ? 1 : 0;
			}
		});
	}
	constructor(baseLayers, overlays, options) {
		super(options);
		this._layerControlInputs = [];
		this._layers = [];
		this._lastZIndex = 0;
		this._handlingClick = false;
		this._preventClick = false;
		for (const [name, layer] of Object.entries(baseLayers ?? {})) this._addLayer(layer, name);
		for (const [name, layer] of Object.entries(overlays ?? {})) this._addLayer(layer, name, true);
		this.callInitHooks(LayersControl);
	}
	onAdd(map) {
		this._initLayout();
		this._update();
		this._map = map;
		map.on("zoomend", this._checkDisabledLayers, this);
		for (const layer of this._layers) layer.layer.on("add remove", this._onLayerChange, this);
		if (!this.options.collapsed) map.on("resize", this._expandIfNotCollapsed, this);
		return this._container;
	}
	addTo(map) {
		super.addTo(map);
		return this._expandIfNotCollapsed();
	}
	onRemove() {
		this._map.off("zoomend", this._checkDisabledLayers, this);
		for (const layer of this._layers) layer.layer.off("add remove", this._onLayerChange, this);
		this._map.off("resize", this._expandIfNotCollapsed, this);
	}
	addBaseLayer(layer, name) {
		this._addLayer(layer, name);
		return this._map ? this._update() : this;
	}
	addOverlay(layer, name) {
		this._addLayer(layer, name, true);
		return this._map ? this._update() : this;
	}
	removeLayer(layer) {
		layer.off("add remove", this._onLayerChange, this);
		const obj = this._getLayer(stamp(layer));
		if (obj) this._layers.splice(this._layers.indexOf(obj), 1);
		return this._map ? this._update() : this;
	}
	expand() {
		clearTimeout(this._collapseDelayTimeout);
		this._container.classList.add("maplair-control-layers-expanded");
		this._section.style.height = null;
		const acceptableHeight = this._map.getSize().y - (this._container.offsetTop + 50);
		if (acceptableHeight < this._section.clientHeight) {
			this._section.classList.add("maplair-control-layers-scrollbar");
			this._section.style.height = `${acceptableHeight}px`;
		} else this._section.classList.remove("maplair-control-layers-scrollbar");
		this._checkDisabledLayers();
		return this;
	}
	collapse(ev) {
		if (!ev || !((ev.type === "pointerleave" || ev.type === "pointerout") && ev.pointerType === "touch")) {
			if (this.options.collapseDelay > 0) {
				this._collapseDelayTimeout = setTimeout(() => {
					this._container.classList.remove("maplair-control-layers-expanded");
				}, this.options.collapseDelay);
				return this;
			}
			this._container.classList.remove("maplair-control-layers-expanded");
		}
		return this;
	}
	_initLayout() {
		const className = "maplair-control-layers", container = this._container = create("div", className), collapsed = this.options.collapsed;
		disableClickPropagation(container);
		disableScrollPropagation(container);
		const section = this._section = create("fieldset", `${className}-list`);
		if (collapsed) {
			this._map.on("click", this.collapse, this);
			on(container, {
				pointerenter: this._expandSafely,
				pointerleave: this.collapse
			}, this);
		}
		const link = this._layersLink = create("a", `${className}-toggle`, container);
		link.href = "#";
		link.title = I18n.translate("Layers");
		link.setAttribute("role", "button");
		on(link, {
			keydown(e) {
				if (e.code === "Enter") this._expandSafely();
			},
			click(e) {
				e.preventDefault();
				this._expandSafely();
			}
		}, this);
		if (!collapsed) this.expand();
		this._baseLayersList = create("div", `${className}-base`, section);
		this._separator = create("div", `${className}-separator`, section);
		this._overlaysList = create("div", `${className}-overlays`, section);
		container.appendChild(section);
	}
	_getLayer(id) {
		for (const layer of this._layers) if (layer && stamp(layer.layer) === id) return layer;
	}
	_addLayer(layer, name, overlay) {
		if (this._map) layer.on("add remove", this._onLayerChange, this);
		this._layers.push({
			layer,
			name,
			overlay
		});
		if (this.options.sortLayers) this._layers.sort(((a, b) => this.options.sortFunction(a.layer, b.layer, a.name, b.name)));
		if (this.options.autoZIndex && layer.setZIndex) {
			this._lastZIndex++;
			layer.setZIndex(this._lastZIndex);
		}
		this._expandIfNotCollapsed();
	}
	_update() {
		if (!this._container) return this;
		this._baseLayersList.replaceChildren();
		this._overlaysList.replaceChildren();
		this._layerControlInputs = [];
		let baseLayersPresent, overlaysPresent, baseLayersCount = 0;
		for (const obj of this._layers) {
			this._addItem(obj);
			overlaysPresent ||= obj.overlay;
			baseLayersPresent ||= !obj.overlay;
			baseLayersCount += !obj.overlay ? 1 : 0;
		}
		if (this.options.hideSingleBase) {
			baseLayersPresent = baseLayersPresent && baseLayersCount > 1;
			this._baseLayersList.style.display = baseLayersPresent ? "" : "none";
		}
		this._separator.style.display = overlaysPresent && baseLayersPresent ? "" : "none";
		return this;
	}
	_onLayerChange(e) {
		if (!this._handlingClick) this._update();
		const obj = this._getLayer(stamp(e.target));
		const type = obj.overlay ? e.type === "add" ? "overlayadd" : "overlayremove" : e.type === "add" ? "baselayerchange" : null;
		if (type) this._map.fire(type, obj);
	}
	_addItem(obj) {
		const label = document.createElement("label"), checked = this._map.hasLayer(obj.layer);
		const input = document.createElement("input");
		input.type = obj.overlay ? "checkbox" : "radio";
		input.className = "maplair-control-layers-selector";
		input.defaultChecked = checked;
		if (!obj.overlay) input.name = `maplair-base-layers_${stamp(this)}`;
		this._layerControlInputs.push(input);
		input.layerId = stamp(obj.layer);
		on(input, "click", this._onInputClick, this);
		const name = document.createElement("span");
		name.innerHTML = ` ${obj.name}`;
		const holder = document.createElement("span");
		label.appendChild(holder);
		holder.appendChild(input);
		holder.appendChild(name);
		(obj.overlay ? this._overlaysList : this._baseLayersList).appendChild(label);
		this._checkDisabledLayers();
		return label;
	}
	_onInputClick(e) {
		if (this._preventClick) return;
		const inputs = this._layerControlInputs, addedLayers = [], removedLayers = [];
		this._handlingClick = true;
		for (const input of inputs) {
			const layer = this._getLayer(input.layerId).layer;
			if (input.checked) addedLayers.push(layer);
			else if (!input.checked) removedLayers.push(layer);
		}
		for (const layer of removedLayers) if (this._map.hasLayer(layer)) this._map.removeLayer(layer);
		for (const layer of addedLayers) if (!this._map.hasLayer(layer)) this._map.addLayer(layer);
		this._handlingClick = false;
		this._refocusOnMap(e);
	}
	_checkDisabledLayers() {
		const inputs = this._layerControlInputs, zoom = this._map.getZoom();
		for (const input of inputs) {
			const layer = this._getLayer(input.layerId).layer;
			input.disabled = layer.options.minZoom !== void 0 && zoom < layer.options.minZoom || layer.options.maxZoom !== void 0 && zoom > layer.options.maxZoom;
		}
	}
	_expandIfNotCollapsed() {
		if (this._map && !this.options.collapsed) this.expand();
		return this;
	}
	_expandSafely() {
		const section = this._section;
		this._preventClick = true;
		on(section, "click", preventDefault);
		this.expand();
		setTimeout(() => {
			off(section, "click", preventDefault);
			this._preventClick = false;
		});
	}
};
//#endregion
//#region src/control/ScaleControl.js
var ScaleControl = class ScaleControl extends Control {
	static {
		this.setDefaultOptions({
			position: "bottomleft",
			maxWidth: 100,
			metric: true,
			imperial: true,
			updateWhenIdle: false
		});
	}
	constructor(...args) {
		super(...args);
		this.callInitHooks(ScaleControl);
	}
	onAdd(map) {
		const className = "maplair-control-scale", container = create("div", className), options = this.options;
		this._addScales(options, `${className}-line`, container);
		map.on(options.updateWhenIdle ? "moveend" : "move", this._update, this);
		map.whenReady(this._update, this);
		return container;
	}
	onRemove(map) {
		map.off(this.options.updateWhenIdle ? "moveend" : "move", this._update, this);
	}
	_addScales(options, className, container) {
		if (options.metric) this._mScale = create("div", className, container);
		if (options.imperial) this._iScale = create("div", className, container);
	}
	_update() {
		const map = this._map, y = map.getSize().y / 2;
		const maxMeters = map.distance(map.containerPointToLatLng([0, y]), map.containerPointToLatLng([this.options.maxWidth, y]));
		this._updateScales(maxMeters);
	}
	_updateScales(maxMeters) {
		if (this.options.metric && maxMeters) this._updateMetric(maxMeters);
		if (this.options.imperial && maxMeters) this._updateImperial(maxMeters);
	}
	_updateMetric(maxMeters) {
		const meters = this._getRoundNum(maxMeters), label = meters < 1e3 ? I18n.translate("{meters} m", { meters }) : I18n.translate("{kilometers} km", { kilometers: meters / 1e3 });
		this._updateScale(this._mScale, label, meters / maxMeters);
	}
	_updateImperial(maxMeters) {
		const maxFeet = maxMeters * 3.2808399;
		let maxMiles, miles, feet;
		if (maxFeet > 5280) {
			maxMiles = maxFeet / 5280;
			miles = this._getRoundNum(maxMiles);
			this._updateScale(this._iScale, I18n.translate("{miles} mi", { miles }), miles / maxMiles);
		} else {
			feet = this._getRoundNum(maxFeet);
			this._updateScale(this._iScale, I18n.translate("{feet} ft", { feet }), feet / maxFeet);
		}
	}
	_updateScale(scale, text, ratio) {
		scale.style.width = `${Math.round(this.options.maxWidth * ratio)}px`;
		scale.innerHTML = text;
	}
	_getRoundNum(num) {
		const pow10 = 10 ** (`${Math.floor(num)}`.length - 1);
		let d = num / pow10;
		d = d >= 10 ? 10 : d >= 5 ? 5 : d >= 3 ? 3 : d >= 2 ? 2 : 1;
		return pow10 * d;
	}
};
//#endregion
//#region src/control/ZoomControl.js
var ZoomControl = class ZoomControl extends Control {
	static {
		this.setDefaultOptions({
			position: "topleft",
			zoomInText: "<span aria-hidden=\"true\">+</span>",
			zoomOutText: "<span aria-hidden=\"true\">&#x2212;</span>"
		});
	}
	constructor(...args) {
		super(...args);
		this.callInitHooks(ZoomControl);
	}
	onAdd(map) {
		const zoomName = "maplair-control-zoom", container = create("div", `${zoomName} maplair-bar`), options = this.options;
		this._zoomInButton = this._createButton(options.zoomInText, I18n.translate("Zoom in"), `${zoomName}-in`, container, this._zoomIn);
		this._zoomOutButton = this._createButton(options.zoomOutText, I18n.translate("Zoom out"), `${zoomName}-out`, container, this._zoomOut);
		this._updateDisabled();
		map.on("zoomend zoomlevelschange", this._updateDisabled, this);
		return container;
	}
	onRemove(map) {
		map.off("zoomend zoomlevelschange", this._updateDisabled, this);
	}
	disable() {
		this._disabled = true;
		this._updateDisabled();
		return this;
	}
	enable() {
		this._disabled = false;
		this._updateDisabled();
		return this;
	}
	_zoomIn(e) {
		if (!this._disabled && this._map._zoom < this._map.getMaxZoom()) this._map.zoomIn(this._map.options.zoomDelta * (e.shiftKey ? 3 : 1));
	}
	_zoomOut(e) {
		if (!this._disabled && this._map._zoom > this._map.getMinZoom()) this._map.zoomOut(this._map.options.zoomDelta * (e.shiftKey ? 3 : 1));
	}
	_createButton(html, title, className, container, fn) {
		const link = create("a", className, container);
		link.innerHTML = html;
		link.href = "#";
		link.title = title;
		link.setAttribute("role", "button");
		link.setAttribute("aria-label", title);
		disableClickPropagation(link);
		on(link, "click", stop);
		on(link, "click", fn, this);
		on(link, "click", this._refocusOnMap, this);
		return link;
	}
	_updateDisabled() {
		const map = this._map, className = "maplair-disabled";
		this._zoomInButton.classList.remove(className);
		this._zoomOutButton.classList.remove(className);
		this._zoomInButton.setAttribute("aria-disabled", "false");
		this._zoomOutButton.setAttribute("aria-disabled", "false");
		if (this._disabled || map._zoom === map.getMinZoom()) {
			this._zoomOutButton.classList.add(className);
			this._zoomOutButton.setAttribute("aria-disabled", "true");
		}
		if (this._disabled || map._zoom === map.getMaxZoom()) {
			this._zoomInButton.classList.add(className);
			this._zoomInButton.setAttribute("aria-disabled", "true");
		}
	}
	static register(MaplairMap) {
		MaplairMap.mergeOptions({ zoomControl: true });
		MaplairMap.addInitHook(function() {
			if (this.options.zoomControl) {
				this.zoomControl = new ZoomControl();
				this.addControl(this.zoomControl);
			}
		});
	}
};
//#endregion
//#region src/core/Events.js
var Evented = class Evented extends Class {
	on(types, fn, context) {
		if (typeof types === "object") for (const [type, f] of Object.entries(types)) this._on(type, f, fn);
		else for (const type of splitWords(types)) this._on(type, fn, context);
		return this;
	}
	off(types, fn, context) {
		if (!arguments.length) {
			delete this._events;
			delete this._listenerIndex;
		} else if (typeof types === "object") for (const [type, f] of Object.entries(types)) this._off(type, f, fn);
		else {
			const removeAll = arguments.length === 1;
			for (const type of splitWords(types)) if (removeAll) this._off(type);
			else this._off(type, fn, context);
		}
		return this;
	}
	static __REMOVED_EVENTS = [
		"mousedown",
		"mouseup",
		"mouseover",
		"mouseout",
		"mousemove"
	];
	_on(type, fn, context, _once) {
		if (Evented.__REMOVED_EVENTS.includes(type)) console.error(`The event ${type} has been removed. Use the PointerEvent variant instead.`);
		if (typeof fn !== "function") {
			console.warn(`wrong listener type: ${typeof fn}`);
			return;
		}
		if (context === this) context = void 0;
		const contexts = this._getListenerIndex(type).get(fn);
		if (contexts?.has(context)) return;
		const newListener = {
			fn,
			ctx: context
		};
		if (_once) newListener.once = true;
		this._events ??= {};
		this._events[type] ??= /* @__PURE__ */ new Set();
		this._events[type].add(newListener);
		if (contexts) contexts.set(context, newListener);
		else this._listenerIndex[type].set(fn, /* @__PURE__ */ new Map([[context, newListener]]));
	}
	_getListenerIndex(type) {
		this._listenerIndex ??= {};
		return this._listenerIndex[type] ??= /* @__PURE__ */ new Map();
	}
	_off(type, fn, context) {
		if (!this._events) return;
		let listeners = this._events[type];
		if (!listeners) return;
		if (arguments.length === 1) {
			if (this._firingCount) for (const listener of listeners) listener.fn = falseFn;
			delete this._events[type];
			delete this._listenerIndex?.[type];
			return;
		}
		if (typeof fn !== "function") {
			console.warn(`wrong listener type: ${typeof fn}`);
			return;
		}
		if (context === this) context = void 0;
		const contexts = this._listenerIndex?.[type]?.get(fn), listener = contexts?.get(context);
		if (listener) {
			contexts.delete(context);
			if (!contexts.size) this._listenerIndex[type].delete(fn);
			if (this._firingCount) {
				listener.fn = falseFn;
				this._events[type] = listeners = new Set(listeners);
			}
			listeners.delete(listener);
		}
	}
	fire(type, data, propagate) {
		if (!this.listens(type, propagate)) return this;
		const event = {
			...data,
			type,
			target: this,
			sourceTarget: data?.sourceTarget || this
		};
		if (this._events) {
			const listeners = this._events[type];
			if (listeners) {
				this._firingCount = this._firingCount + 1 || 1;
				for (const l of listeners) {
					const fn = l.fn;
					if (l.once) this.off(type, fn, l.ctx);
					fn.call(l.ctx || this, event);
				}
				this._firingCount--;
			}
		}
		if (propagate) this._propagateEvent(event);
		return this;
	}
	listens(type, fn, context, propagate) {
		if (typeof type !== "string") console.warn("\"string\" type argument expected");
		let _fn = fn;
		if (typeof fn !== "function") {
			propagate = !!fn;
			_fn = void 0;
			context = void 0;
		}
		if (this._events?.[type]?.size) {
			if (this._listens(type, _fn, context) !== false) return true;
		}
		if (propagate) {
			for (const p of Object.values(this._eventParents ?? {})) if (p.listens(type, fn, context, propagate)) return true;
		}
		return false;
	}
	_listens(type, fn, context) {
		if (!this._events) return false;
		const listeners = this._events[type];
		if (!fn) return !!listeners?.size;
		if (context === this) context = void 0;
		return !!this._listenerIndex?.[type]?.get(fn)?.has(context);
	}
	once(types, fn, context) {
		if (typeof types === "object") for (const [type, f] of Object.entries(types)) this._on(type, f, fn, true);
		else for (const type of splitWords(types)) this._on(type, fn, context, true);
		return this;
	}
	addEventParent(obj) {
		this._eventParents ??= {};
		this._eventParents[stamp(obj)] = obj;
		return this;
	}
	removeEventParent(obj) {
		if (this._eventParents) delete this._eventParents[stamp(obj)];
		return this;
	}
	_propagateEvent(e) {
		for (const p of Object.values(this._eventParents ?? {})) p.fire(e.type, {
			propagatedFrom: e.target,
			...e
		}, true);
	}
};
//#endregion
//#region src/core/Handler.js
var Handler = class Handler extends Class {
	constructor(map) {
		super();
		this._map = map;
		this.callInitHooks(Handler);
	}
	enable() {
		if (this._enabled) return this;
		this._enabled = true;
		this.addHooks();
		return this;
	}
	disable() {
		if (!this._enabled) return this;
		this._enabled = false;
		this.removeHooks();
		return this;
	}
	enabled() {
		return !!this._enabled;
	}
};
Handler.addTo = function(map, name) {
	map.addHandler(name, this);
	return this;
};
//#endregion
//#region src/dom/PosAnimation.js
var PosAnimation = class PosAnimation extends Evented {
	constructor(...args) {
		super(...args);
		this.callInitHooks(PosAnimation);
	}
	run(el, newPos, duration, easeLinearity) {
		this.stop();
		this._el = el;
		this._inProgress = true;
		this._duration = duration ?? .25;
		this._easeOutPower = 1 / Math.max(easeLinearity ?? .5, .2);
		this._startPos = getPosition(el);
		this._offset = newPos.subtract(this._startPos);
		this._startTime = Date.now();
		this.fire("start");
		this._animate();
	}
	stop() {
		if (!this._inProgress) return;
		this._step(true);
		this._complete();
	}
	_animate() {
		this._animId = requestAnimationFrame(this._animate.bind(this));
		this._step();
	}
	_step(round) {
		const elapsed = Date.now() - this._startTime, duration = this._duration * 1e3;
		if (elapsed < duration) this._runFrame(this._easeOut(elapsed / duration), round);
		else {
			this._runFrame(1);
			this._complete();
		}
	}
	_runFrame(progress, round) {
		const pos = this._startPos.add(this._offset.multiplyBy(progress));
		if (round) pos._round();
		setPosition(this._el, pos);
		this.fire("step");
	}
	_complete() {
		cancelAnimationFrame(this._animId);
		this._inProgress = false;
		this.fire("end");
	}
	_easeOut(t) {
		return 1 - (1 - t) ** this._easeOutPower;
	}
};
//#endregion
//#region src/dom/Draggable.js
var Draggable = class Draggable extends Evented {
	static {
		this.setDefaultOptions({ clickTolerance: 3 });
	}
	constructor(element, dragStartTarget, preventOutline, options) {
		super();
		setOptions(this, options);
		this._element = element;
		this._dragStartTarget = dragStartTarget ?? element;
		this._preventOutline = preventOutline;
		this.callInitHooks(Draggable);
	}
	enable() {
		if (this._enabled) return;
		on(this._dragStartTarget, "pointerdown", this._onDown, this);
		this._enabled = true;
	}
	disable() {
		if (!this._enabled) return;
		if (Draggable._dragging === this) this.finishDrag(true);
		off(this._dragStartTarget, "pointerdown", this._onDown, this);
		this._enabled = false;
		this._moved = false;
	}
	_onDown(e) {
		this._moved = false;
		if (this._element.classList.contains("maplair-zoom-anim")) return;
		if (getPointers().length !== 1) {
			if (Draggable._dragging === this) this.finishDrag();
			return;
		}
		if (Draggable._dragging || e.shiftKey || e.button !== 0 && e.pointerType !== "touch") return;
		Draggable._dragging = this;
		if (this._preventOutline) preventOutline(this._element);
		disableImageDrag();
		disableTextSelection();
		if (this._moving) return;
		this.fire("down");
		const sizedParent = getSizedParentNode(this._element);
		this._startPoint = new Point(e.clientX, e.clientY);
		this._startPos = getPosition(this._element);
		this._parentScale = getScale(sizedParent);
		on(this._dragStartTarget, "pointermove", this._onMove, this);
		on(this._dragStartTarget, "pointerup pointercancel", this._onUp, this);
	}
	_onMove(e) {
		if (getPointers().length > 1) {
			this._moved = true;
			return;
		}
		const offset = new Point(e.clientX, e.clientY)._subtract(this._startPoint);
		if (!offset.x && !offset.y) return;
		if (Math.abs(offset.x) + Math.abs(offset.y) < this.options.clickTolerance) return;
		offset.x /= this._parentScale.x;
		offset.y /= this._parentScale.y;
		if (e.cancelable) e.preventDefault();
		if (!this._moved) {
			this.fire("dragstart");
			this._moved = true;
			this._element.ownerDocument.body.classList.add("maplair-dragging");
			this._lastTarget = e.target ?? e.srcElement;
			this._lastTarget.classList.add("maplair-drag-target");
		}
		this._newPos = this._startPos.add(offset);
		this._moving = true;
		this._lastEvent = e;
		this._updatePosition();
	}
	_updatePosition() {
		const e = { originalEvent: this._lastEvent };
		this.fire("predrag", e);
		setPosition(this._element, this._newPos);
		this.fire("drag", e);
	}
	_onUp() {
		this.finishDrag();
	}
	finishDrag(noInertia) {
		this._element.ownerDocument.body.classList.remove("maplair-dragging");
		if (this._lastTarget) {
			this._lastTarget.classList.remove("maplair-drag-target");
			this._lastTarget = null;
		}
		off(this._dragStartTarget, "pointermove", this._onMove, this);
		off(this._dragStartTarget, "pointerup pointercancel", this._onUp, this);
		enableImageDrag();
		enableTextSelection();
		const fireDragend = this._moved && this._moving;
		this._moving = false;
		Draggable._dragging = false;
		if (fireDragend) this.fire("dragend", {
			noInertia,
			distance: this._newPos.distanceTo(this._startPos)
		});
	}
};
//#endregion
//#region src/geometry/Bounds.js
var Bounds = class Bounds {
	constructor(a, b) {
		if (!a) return;
		if (a instanceof Bounds) {
			if (a.isValid()) {
				this.min = new Point(a.min);
				this.max = new Point(a.max);
			}
			return;
		}
		const points = b ? [a, b] : a;
		for (const point of points) this.extend(point);
	}
	extend(obj) {
		let min2, max2;
		if (!obj) return this;
		if (obj instanceof Point || typeof obj[0] === "number" || "x" in obj) min2 = max2 = new Point(obj);
		else {
			obj = new Bounds(obj);
			min2 = obj.min;
			max2 = obj.max;
			if (!min2 || !max2) return this;
		}
		if (!this.min && !this.max) {
			this.min = new Point(min2);
			this.max = new Point(max2);
		} else {
			this.min.x = Math.min(min2.x, this.min.x);
			this.max.x = Math.max(max2.x, this.max.x);
			this.min.y = Math.min(min2.y, this.min.y);
			this.max.y = Math.max(max2.y, this.max.y);
		}
		return this;
	}
	getCenter(round) {
		return new Point((this.min.x + this.max.x) / 2, (this.min.y + this.max.y) / 2, round);
	}
	getBottomLeft() {
		return new Point(this.min.x, this.max.y);
	}
	getTopRight() {
		return new Point(this.max.x, this.min.y);
	}
	getTopLeft() {
		return this.min;
	}
	getBottomRight() {
		return this.max;
	}
	getSize() {
		return this.max.subtract(this.min);
	}
	contains(obj) {
		let min, max;
		if (typeof obj[0] === "number" || obj instanceof Point) obj = new Point(obj);
		else obj = new Bounds(obj);
		if (obj instanceof Bounds) {
			min = obj.min;
			max = obj.max;
		} else min = max = obj;
		return min.x >= this.min.x && max.x <= this.max.x && min.y >= this.min.y && max.y <= this.max.y;
	}
	intersects(bounds) {
		bounds = new Bounds(bounds);
		const min = this.min, max = this.max, min2 = bounds.min, max2 = bounds.max, xIntersects = max2.x >= min.x && min2.x <= max.x, yIntersects = max2.y >= min.y && min2.y <= max.y;
		return xIntersects && yIntersects;
	}
	overlaps(bounds) {
		bounds = new Bounds(bounds);
		const min = this.min, max = this.max, min2 = bounds.min, max2 = bounds.max, xOverlaps = max2.x > min.x && min2.x < max.x, yOverlaps = max2.y > min.y && min2.y < max.y;
		return xOverlaps && yOverlaps;
	}
	isValid() {
		return !!(this.min && this.max);
	}
	pad(bufferRatio) {
		const min = this.min, max = this.max, heightBuffer = Math.abs(min.x - max.x) * bufferRatio, widthBuffer = Math.abs(min.y - max.y) * bufferRatio;
		return new Bounds(new Point(min.x - heightBuffer, min.y - widthBuffer), new Point(max.x + heightBuffer, max.y + widthBuffer));
	}
	equals(bounds) {
		if (!bounds) return false;
		bounds = new Bounds(bounds);
		return this.min.equals(bounds.getTopLeft()) && this.max.equals(bounds.getBottomRight());
	}
};
//#endregion
//#region src/geometry/Transformation.js
var Transformation = class {
	constructor(a, b, c, d) {
		if (Array.isArray(a)) {
			this._a = a[0];
			this._b = a[1];
			this._c = a[2];
			this._d = a[3];
			return;
		}
		this._a = a;
		this._b = b;
		this._c = c;
		this._d = d;
	}
	transform(point, scale) {
		return this._transform(new Point(point), scale);
	}
	_transform(point, scale) {
		scale ||= 1;
		point.x = scale * (this._a * point.x + this._b);
		point.y = scale * (this._c * point.y + this._d);
		return point;
	}
	untransform(point, scale) {
		scale ||= 1;
		return new Point((point.x / scale - this._b) / this._a, (point.y / scale - this._d) / this._c);
	}
};
//#endregion
//#region src/geo/LatLngBounds.js
var LatLngBounds = class LatLngBounds {
	constructor(corner1, corner2) {
		if (!corner1) return;
		if (corner1 instanceof LatLngBounds) {
			if (corner1.isValid()) {
				this._southWest = new LatLng(corner1._southWest);
				this._northEast = new LatLng(corner1._northEast);
			}
			return;
		}
		const latlngs = corner2 ? [corner1, corner2] : corner1;
		for (const latlng of latlngs) this.extend(latlng);
	}
	extend(obj) {
		const sw = this._southWest, ne = this._northEast;
		let sw2, ne2;
		if (obj instanceof LatLng) {
			sw2 = obj;
			ne2 = obj;
		} else if (obj instanceof LatLngBounds) {
			sw2 = obj._southWest;
			ne2 = obj._northEast;
			if (!sw2 || !ne2) return this;
		} else {
			if (!obj) return this;
			if (LatLng.validate(obj)) return this.extend(new LatLng(obj));
			return this.extend(new LatLngBounds(obj));
		}
		if (!sw && !ne) {
			this._southWest = new LatLng(sw2.lat, sw2.lng);
			this._northEast = new LatLng(ne2.lat, ne2.lng);
		} else {
			sw.lat = Math.min(sw2.lat, sw.lat);
			sw.lng = Math.min(sw2.lng, sw.lng);
			ne.lat = Math.max(ne2.lat, ne.lat);
			ne.lng = Math.max(ne2.lng, ne.lng);
		}
		return this;
	}
	pad(bufferRatio) {
		const sw = this._southWest, ne = this._northEast, heightBuffer = Math.abs(sw.lat - ne.lat) * bufferRatio, widthBuffer = Math.abs(sw.lng - ne.lng) * bufferRatio;
		return new LatLngBounds(new LatLng(sw.lat - heightBuffer, sw.lng - widthBuffer), new LatLng(ne.lat + heightBuffer, ne.lng + widthBuffer));
	}
	getCenter() {
		return new LatLng((this._southWest.lat + this._northEast.lat) / 2, (this._southWest.lng + this._northEast.lng) / 2);
	}
	getSouthWest() {
		return this._southWest;
	}
	getNorthEast() {
		return this._northEast;
	}
	getNorthWest() {
		return new LatLng(this.getNorth(), this.getWest());
	}
	getSouthEast() {
		return new LatLng(this.getSouth(), this.getEast());
	}
	getWest() {
		return this._southWest.lng;
	}
	getSouth() {
		return this._southWest.lat;
	}
	getEast() {
		return this._northEast.lng;
	}
	getNorth() {
		return this._northEast.lat;
	}
	contains(obj) {
		if (LatLng.validate(obj)) obj = new LatLng(obj);
		else obj = new LatLngBounds(obj);
		const sw = this._southWest, ne = this._northEast;
		let sw2, ne2;
		if (obj instanceof LatLngBounds) {
			sw2 = obj.getSouthWest();
			ne2 = obj.getNorthEast();
		} else sw2 = ne2 = obj;
		return sw2.lat >= sw.lat && ne2.lat <= ne.lat && sw2.lng >= sw.lng && ne2.lng <= ne.lng;
	}
	intersects(bounds) {
		bounds = new LatLngBounds(bounds);
		const sw = this._southWest, ne = this._northEast, sw2 = bounds.getSouthWest(), ne2 = bounds.getNorthEast(), latIntersects = ne2.lat >= sw.lat && sw2.lat <= ne.lat, lngIntersects = ne2.lng >= sw.lng && sw2.lng <= ne.lng;
		return latIntersects && lngIntersects;
	}
	overlaps(bounds) {
		bounds = new LatLngBounds(bounds);
		const sw = this._southWest, ne = this._northEast, sw2 = bounds.getSouthWest(), ne2 = bounds.getNorthEast(), latOverlaps = ne2.lat > sw.lat && sw2.lat < ne.lat, lngOverlaps = ne2.lng > sw.lng && sw2.lng < ne.lng;
		return latOverlaps && lngOverlaps;
	}
	toBBoxString() {
		return [
			this.getWest(),
			this.getSouth(),
			this.getEast(),
			this.getNorth()
		].join(",");
	}
	equals(bounds, maxMargin) {
		if (!bounds) return false;
		bounds = new LatLngBounds(bounds);
		return this._southWest.equals(bounds.getSouthWest(), maxMargin) && this._northEast.equals(bounds.getNorthEast(), maxMargin);
	}
	isValid() {
		return !!(this._southWest && this._northEast);
	}
};
//#endregion
//#region src/geo/crs/CRS.js
var CRS = class {
	static projection = void 0;
	static transformation = void 0;
	static latLngToPoint(latlng, zoom) {
		const projectedPoint = this.projection.project(latlng), scale = this.scale(zoom);
		return this.transformation._transform(projectedPoint, scale);
	}
	static pointToLatLng(point, zoom) {
		const scale = this.scale(zoom), untransformedPoint = this.transformation.untransform(point, scale);
		return this.projection.unproject(untransformedPoint);
	}
	static project(latlng) {
		return this.projection.project(latlng);
	}
	static unproject(point) {
		return this.projection.unproject(point);
	}
	static scale(zoom) {
		return 256 * 2 ** zoom;
	}
	static zoom(scale) {
		return Math.log(scale / 256) / Math.LN2;
	}
	static getProjectedBounds(zoom) {
		if (this.infinite) return null;
		const b = this.projection.bounds, s = this.scale(zoom);
		return new Bounds(this.transformation.transform(b.min, s), this.transformation.transform(b.max, s));
	}
	static infinite = false;
	static wrapLatLng(latlng) {
		latlng = new LatLng(latlng);
		const lng = this.wrapLng ? wrapNum(latlng.lng, this.wrapLng, true) : latlng.lng, lat = this.wrapLat ? wrapNum(latlng.lat, this.wrapLat, true) : latlng.lat, alt = latlng.alt;
		return new LatLng(lat, lng, alt);
	}
	static wrapLatLngBounds(bounds) {
		bounds = new LatLngBounds(bounds);
		const center = bounds.getCenter(), newCenter = this.wrapLatLng(center), latShift = center.lat - newCenter.lat, lngShift = center.lng - newCenter.lng;
		if (latShift === 0 && lngShift === 0) return bounds;
		const sw = bounds.getSouthWest(), ne = bounds.getNorthEast();
		return new LatLngBounds(new LatLng(sw.lat - latShift, sw.lng - lngShift), new LatLng(ne.lat - latShift, ne.lng - lngShift));
	}
};
//#endregion
//#region src/geo/crs/EarthCRS.js
var EarthCRS = class extends CRS {
	static wrapLng = [-180, 180];
	static R = 6371e3;
	static distance(latlng1, latlng2) {
		const rad = Math.PI / 180, lat1 = latlng1.lat * rad, lat2 = latlng2.lat * rad, sinDLat = Math.sin((latlng2.lat - latlng1.lat) * rad / 2), sinDLon = Math.sin((latlng2.lng - latlng1.lng) * rad / 2), a = sinDLat * sinDLat + Math.cos(lat1) * Math.cos(lat2) * sinDLon * sinDLon, c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
		return this.R * c;
	}
};
//#endregion
//#region src/geo/LatLng.js
var LatLng = class LatLng {
	constructor(lat, lng, alt) {
		if (!LatLng.validate(lat, lng, alt)) throw new Error(`Invalid LatLng object: (${lat}, ${lng})`);
		let _lat, _lng, _alt;
		if (lat instanceof LatLng) {
			_lat = lat.lat;
			_lng = lat.lng;
			_alt = lat.alt;
		} else if (Array.isArray(lat) && typeof lat[0] !== "object") {
			if (lat.length === 3) {
				_lat = lat[0];
				_lng = lat[1];
				_alt = lat[2];
			} else if (lat.length === 2) {
				_lat = lat[0];
				_lng = lat[1];
			}
		} else if (typeof lat === "object" && "lat" in lat) {
			_lat = lat.lat;
			_lng = "lng" in lat ? lat.lng : lat.lon;
			_alt = lat.alt;
		} else {
			_lat = lat;
			_lng = lng;
			_alt = alt;
		}
		this.lat = +_lat;
		this.lng = +_lng;
		if (_alt !== void 0) this.alt = +_alt;
	}
	static validate(lat, lng, alt) {
		if (lat instanceof LatLng || typeof lat === "object" && lat !== null && "lat" in lat) return true;
		else if (lat && Array.isArray(lat) && typeof lat[0] !== "object") {
			if (lat.length === 3 || lat.length === 2) return true;
			return false;
		} else if ((lat || lat === 0) && (lng || lng === 0)) return true;
		return false;
	}
	equals(obj, maxMargin) {
		if (!obj) return false;
		obj = new LatLng(obj);
		return Math.max(Math.abs(this.lat - obj.lat), Math.abs(this.lng - obj.lng)) <= (maxMargin ?? 1e-9);
	}
	toString(precision) {
		return `LatLng(${formatNum(this.lat, precision)}, ${formatNum(this.lng, precision)})`;
	}
	distanceTo(other) {
		return EarthCRS.distance(this, new LatLng(other));
	}
	wrap() {
		return EarthCRS.wrapLatLng(this);
	}
	toBounds(sizeInMeters) {
		const latAccuracy = 180 * sizeInMeters / 40075017, lngAccuracy = latAccuracy / Math.cos(Math.PI / 180 * this.lat);
		return new LatLngBounds([this.lat - latAccuracy, this.lng - lngAccuracy], [this.lat + latAccuracy, this.lng + lngAccuracy]);
	}
};
//#endregion
//#region src/geometry/PolyUtil.js
var PolyUtil_exports = /* @__PURE__ */ __exportAll({
	centroid: () => centroid,
	clipPolygon: () => clipPolygon,
	polygonCenter: () => polygonCenter
});
function clipPolygon(points, bounds, round) {
	let clippedPoints, i, j, k, a, b, len, edge, p;
	const edges = [
		1,
		4,
		2,
		8
	];
	for (i = 0, len = points.length; i < len; i++) points[i]._code = _getBitCode(points[i], bounds);
	for (k = 0; k < 4; k++) {
		edge = edges[k];
		clippedPoints = [];
		for (i = 0, len = points.length, j = len - 1; i < len; j = i++) {
			a = points[i];
			b = points[j];
			if (!(a._code & edge)) {
				if (b._code & edge) {
					p = _getEdgeIntersection(b, a, edge, bounds, round);
					p._code = _getBitCode(p, bounds);
					clippedPoints.push(p);
				}
				clippedPoints.push(a);
			} else if (!(b._code & edge)) {
				p = _getEdgeIntersection(b, a, edge, bounds, round);
				p._code = _getBitCode(p, bounds);
				clippedPoints.push(p);
			}
		}
		points = clippedPoints;
	}
	return points;
}
function polygonCenter(latlngs, crs) {
	let i, j, p1, p2, f, area, x, y, center;
	if (!latlngs || latlngs.length === 0) throw new Error("latlngs not passed");
	if (!isFlat(latlngs)) {
		console.warn("latlngs are not flat! Only the first ring will be used");
		latlngs = latlngs[0];
	}
	let centroidLatLng = new LatLng([0, 0]);
	const bounds = new LatLngBounds(latlngs);
	if (bounds.getNorthWest().distanceTo(bounds.getSouthWest()) * bounds.getNorthEast().distanceTo(bounds.getNorthWest()) < 1700) centroidLatLng = centroid(latlngs);
	const len = latlngs.length;
	const points = [];
	for (i = 0; i < len; i++) {
		const latlng = new LatLng(latlngs[i]);
		points.push(crs.project(new LatLng([latlng.lat - centroidLatLng.lat, latlng.lng - centroidLatLng.lng])));
	}
	area = x = y = 0;
	for (i = 0, j = len - 1; i < len; j = i++) {
		p1 = points[i];
		p2 = points[j];
		f = p1.y * p2.x - p2.y * p1.x;
		x += (p1.x + p2.x) * f;
		y += (p1.y + p2.y) * f;
		area += f * 3;
	}
	if (area === 0) center = points[0];
	else center = [x / area, y / area];
	const latlngCenter = crs.unproject(new Point(center));
	return new LatLng([latlngCenter.lat + centroidLatLng.lat, latlngCenter.lng + centroidLatLng.lng]);
}
function centroid(coords) {
	let latSum = 0;
	let lngSum = 0;
	let len = 0;
	for (const coord of coords) {
		const latlng = new LatLng(coord);
		latSum += latlng.lat;
		lngSum += latlng.lng;
		len++;
	}
	return new LatLng([latSum / len, lngSum / len]);
}
//#endregion
//#region src/geometry/LineUtil.js
var LineUtil_exports = /* @__PURE__ */ __exportAll({
	_getBitCode: () => _getBitCode,
	_getEdgeIntersection: () => _getEdgeIntersection,
	_sqClosestPointOnSegment: () => _sqClosestPointOnSegment,
	clipSegment: () => clipSegment,
	closestPointOnSegment: () => closestPointOnSegment,
	isFlat: () => isFlat,
	pointToSegmentDistance: () => pointToSegmentDistance,
	polylineCenter: () => polylineCenter,
	simplify: () => simplify
});
function simplify(points, tolerance) {
	if (!tolerance || !points.length) return points.slice();
	const sqTolerance = tolerance * tolerance;
	points = _reducePoints(points, sqTolerance);
	points = _simplifyDP(points, sqTolerance);
	return points;
}
function pointToSegmentDistance(p, p1, p2) {
	return Math.sqrt(_sqClosestPointOnSegment(p, p1, p2, true));
}
function closestPointOnSegment(p, p1, p2) {
	return _sqClosestPointOnSegment(p, p1, p2);
}
function _simplifyDP(points, sqTolerance) {
	const len = points.length, markers = new Uint8Array(len);
	markers[0] = markers[len - 1] = 1;
	_simplifyDPStep(points, markers, sqTolerance, 0, len - 1);
	let i;
	const newPoints = [];
	for (i = 0; i < len; i++) if (markers[i]) newPoints.push(points[i]);
	return newPoints;
}
function _simplifyDPStep(points, markers, sqTolerance, first, last) {
	let maxSqDist = 0, index, i, sqDist;
	for (i = first + 1; i <= last - 1; i++) {
		sqDist = _sqClosestPointOnSegment(points[i], points[first], points[last], true);
		if (sqDist > maxSqDist) {
			index = i;
			maxSqDist = sqDist;
		}
	}
	if (maxSqDist > sqTolerance) {
		markers[index] = 1;
		_simplifyDPStep(points, markers, sqTolerance, first, index);
		_simplifyDPStep(points, markers, sqTolerance, index, last);
	}
}
function _reducePoints(points, sqTolerance) {
	const reducedPoints = [points[0]];
	let prev = 0;
	for (let i = 1; i < points.length; i++) if (_sqDist(points[i], points[prev]) > sqTolerance) {
		reducedPoints.push(points[i]);
		prev = i;
	}
	if (prev < points.length - 1) reducedPoints.push(points[points.length - 1]);
	return reducedPoints;
}
let _lastCode;
function clipSegment(a, b, bounds, useLastCode, round) {
	let codeA = useLastCode ? _lastCode : _getBitCode(a, bounds), codeB = _getBitCode(b, bounds), codeOut, p, newCode;
	_lastCode = codeB;
	while (true) {
		if (!(codeA | codeB)) return [a, b];
		if (codeA & codeB) return false;
		codeOut = codeA || codeB;
		p = _getEdgeIntersection(a, b, codeOut, bounds, round);
		newCode = _getBitCode(p, bounds);
		if (codeOut === codeA) {
			a = p;
			codeA = newCode;
		} else {
			b = p;
			codeB = newCode;
		}
	}
}
function _getEdgeIntersection(a, b, code, bounds, round) {
	const dx = b.x - a.x, dy = b.y - a.y, min = bounds.min, max = bounds.max;
	let x, y;
	if (code & 8) {
		x = a.x + dx * (max.y - a.y) / dy;
		y = max.y;
	} else if (code & 4) {
		x = a.x + dx * (min.y - a.y) / dy;
		y = min.y;
	} else if (code & 2) {
		x = max.x;
		y = a.y + dy * (max.x - a.x) / dx;
	} else if (code & 1) {
		x = min.x;
		y = a.y + dy * (min.x - a.x) / dx;
	}
	return new Point(x, y, round);
}
function _getBitCode(p, bounds) {
	let code = 0;
	if (p.x < bounds.min.x) code |= 1;
	else if (p.x > bounds.max.x) code |= 2;
	if (p.y < bounds.min.y) code |= 4;
	else if (p.y > bounds.max.y) code |= 8;
	return code;
}
function _sqDist(p1, p2) {
	const dx = p2.x - p1.x, dy = p2.y - p1.y;
	return dx * dx + dy * dy;
}
function _sqClosestPointOnSegment(p, p1, p2, sqDist) {
	let x = p1.x, y = p1.y, dx = p2.x - x, dy = p2.y - y, t;
	const dot = dx * dx + dy * dy;
	if (dot > 0) {
		t = ((p.x - x) * dx + (p.y - y) * dy) / dot;
		if (t > 1) {
			x = p2.x;
			y = p2.y;
		} else if (t > 0) {
			x += dx * t;
			y += dy * t;
		}
	}
	dx = p.x - x;
	dy = p.y - y;
	return sqDist ? dx * dx + dy * dy : new Point(x, y);
}
function isFlat(latlngs) {
	return !Array.isArray(latlngs[0]) || typeof latlngs[0][0] !== "object" && typeof latlngs[0][0] !== "undefined";
}
function polylineCenter(latlngs, crs) {
	let i, halfDist, segDist, dist, p1, p2, ratio, center;
	if (!latlngs || latlngs.length === 0) throw new Error("latlngs not passed");
	if (!isFlat(latlngs)) {
		console.warn("latlngs are not flat! Only the first ring will be used");
		latlngs = latlngs[0];
	}
	let centroidLatLng = new LatLng([0, 0]);
	const bounds = new LatLngBounds(latlngs);
	if (bounds.getNorthWest().distanceTo(bounds.getSouthWest()) * bounds.getNorthEast().distanceTo(bounds.getNorthWest()) < 1700) centroidLatLng = centroid(latlngs);
	const len = latlngs.length;
	const points = [];
	for (i = 0; i < len; i++) {
		const latlng = new LatLng(latlngs[i]);
		points.push(crs.project(new LatLng([latlng.lat - centroidLatLng.lat, latlng.lng - centroidLatLng.lng])));
	}
	for (i = 0, halfDist = 0; i < len - 1; i++) halfDist += points[i].distanceTo(points[i + 1]) / 2;
	if (halfDist === 0) center = points[0];
	else for (i = 0, dist = 0; i < len - 1; i++) {
		p1 = points[i];
		p2 = points[i + 1];
		segDist = p1.distanceTo(p2);
		dist += segDist;
		if (dist > halfDist) {
			ratio = (dist - halfDist) / segDist;
			center = [p2.x - ratio * (p2.x - p1.x), p2.y - ratio * (p2.y - p1.y)];
			break;
		}
	}
	const latlngCenter = crs.unproject(new Point(center));
	return new LatLng([latlngCenter.lat + centroidLatLng.lat, latlngCenter.lng + centroidLatLng.lng]);
}
//#endregion
//#region src/geo/projection/Projection.LonLat.js
const LonLat = {
	project(latlng) {
		latlng = new LatLng(latlng);
		return new Point(latlng.lng, latlng.lat);
	},
	unproject(point) {
		point = new Point(point);
		return new LatLng(point.y, point.x);
	},
	bounds: new Bounds([-180, -90], [180, 90])
};
const Mercator = {
	R: 6378137,
	R_MINOR: 6356752.314245179,
	bounds: new Bounds([-20037508.34279, -15496570.73972], [20037508.34279, 18764656.23138]),
	project(latlng) {
		latlng = new LatLng(latlng);
		const d = Math.PI / 180, r = this.R, tmp = this.R_MINOR / r, e = Math.sqrt(1 - tmp * tmp);
		let y = latlng.lat * d;
		const con = e * Math.sin(y);
		const ts = Math.tan(Math.PI / 4 - y / 2) / ((1 - con) / (1 + con)) ** (e / 2);
		y = -r * Math.log(Math.max(ts, 1e-10));
		return new Point(latlng.lng * d * r, y);
	},
	unproject(point) {
		point = new Point(point);
		const d = 180 / Math.PI, r = this.R, tmp = this.R_MINOR / r, e = Math.sqrt(1 - tmp * tmp), ts = Math.exp(-point.y / r);
		let phi = Math.PI / 2 - 2 * Math.atan(ts);
		for (let i = 0, dphi = .1, con; i < 15 && Math.abs(dphi) > 1e-7; i++) {
			con = e * Math.sin(phi);
			con = ((1 - con) / (1 + con)) ** (e / 2);
			dphi = Math.PI / 2 - 2 * Math.atan(ts * con) - phi;
			phi += dphi;
		}
		return new LatLng(phi * d, point.x * d / r);
	}
};
//#endregion
//#region src/geo/projection/Projection.SphericalMercator.js
const earthRadius = 6378137;
const SphericalMercator = {
	R: earthRadius,
	MAX_LATITUDE: 85.0511287798,
	project(latlng) {
		latlng = new LatLng(latlng);
		const d = Math.PI / 180, max = this.MAX_LATITUDE, lat = Math.max(Math.min(max, latlng.lat), -max), sin = Math.sin(lat * d);
		return new Point(this.R * latlng.lng * d, this.R * Math.log((1 + sin) / (1 - sin)) / 2);
	},
	unproject(point) {
		point = new Point(point);
		const d = 180 / Math.PI;
		return new LatLng((2 * Math.atan(Math.exp(point.y / this.R)) - Math.PI / 2) * d, point.x * d / this.R);
	},
	bounds: (() => {
		const d = earthRadius * Math.PI;
		return new Bounds([-d, -d], [d, d]);
	})()
};
//#endregion
//#region src/geo/projection/index.js
var projection_exports = /* @__PURE__ */ __exportAll({
	LonLat: () => LonLat,
	Mercator: () => Mercator,
	SphericalMercator: () => SphericalMercator
});
//#endregion
//#region src/geo/crs/EPSG3395.js
var EPSG3395 = class extends EarthCRS {
	static code = "EPSG:3395";
	static projection = Mercator;
	static transformation = (() => {
		const scale = .5 / (Math.PI * Mercator.R);
		return new Transformation(scale, .5, -scale, .5);
	})();
};
//#endregion
//#region src/geo/crs/EPSG3857.js
var EPSG3857 = class extends EarthCRS {
	static code = "EPSG:3857";
	static projection = SphericalMercator;
	static transformation = (() => {
		const scale = .5 / (Math.PI * SphericalMercator.R);
		return new Transformation(scale, .5, -scale, .5);
	})();
};
var EPSG900913 = class extends EPSG3857 {
	static code = "EPSG:900913";
};
//#endregion
//#region src/geo/crs/EPSG4326.js
var EPSG4326 = class extends EarthCRS {
	static code = "EPSG:4326";
	static projection = LonLat;
	static transformation = new Transformation(1 / 180, 1, -1 / 180, .5);
};
//#endregion
//#region src/geo/crs/SimpleCRS.js
var SimpleCRS = class extends CRS {
	static projection = LonLat;
	static transformation = new Transformation(1, 0, -1, 0);
	static scale(zoom) {
		return 2 ** zoom;
	}
	static zoom(scale) {
		return Math.log(scale) / Math.LN2;
	}
	static distance(latlng1, latlng2) {
		const dx = latlng2.lng - latlng1.lng, dy = latlng2.lat - latlng1.lat;
		return Math.sqrt(dx * dx + dy * dy);
	}
	static infinite = true;
};
//#endregion
//#region src/layer/Layer.js
var Layer = class extends Evented {
	static {
		this.setDefaultOptions({
			pane: "overlayPane",
			attribution: null,
			bubblingPointerEvents: true
		});
	}
	addTo(map) {
		map.addLayer(this);
		return this;
	}
	remove() {
		return this.removeFrom(this._map || this._mapToAdd);
	}
	removeFrom(obj) {
		obj?.removeLayer(this);
		return this;
	}
	getPane(name) {
		return this._map.getPane(name ? this.options[name] || name : this.options.pane);
	}
	addInteractiveTarget(targetEl) {
		this._map._targets[stamp(targetEl)] = this;
		return this;
	}
	removeInteractiveTarget(targetEl) {
		delete this._map._targets[stamp(targetEl)];
		return this;
	}
	getAttribution() {
		return this.options.attribution;
	}
	_layerAdd(e) {
		const map = e.target;
		if (!map.hasLayer(this)) return;
		this._map = map;
		this._zoomAnimated = map._zoomAnimated;
		if (this.getEvents) {
			const events = this.getEvents();
			map.on(events, this);
			this.once("remove", () => map.off(events, this));
		}
		this.onAdd(map);
		this.fire("add");
		map.fire("layeradd", { layer: this });
	}
	static register(MaplairMap) {
		MaplairMap.include({
			addLayer(layer) {
				if (!layer._layerAdd) throw new Error("The provided object is not a Layer.");
				const id = stamp(layer);
				if (this._layers[id]) return this;
				this._layers[id] = layer;
				layer._mapToAdd = this;
				if (layer.beforeAdd) layer.beforeAdd(this);
				this.whenReady(layer._layerAdd, layer);
				return this;
			},
			removeLayer(layer) {
				const id = stamp(layer);
				if (!this._layers[id]) return this;
				if (this._loaded) layer.onRemove(this);
				delete this._layers[id];
				if (this._loaded) {
					this.fire("layerremove", { layer });
					layer.fire("remove");
				}
				layer._map = layer._mapToAdd = null;
				return this;
			},
			hasLayer(layer) {
				return stamp(layer) in this._layers;
			},
			eachLayer(method, context) {
				for (const layer of Object.values(this._layers)) method.call(context, layer);
				return this;
			},
			_addLayers(layers) {
				layers = layers ? Array.isArray(layers) ? layers : [layers] : [];
				for (const layer of layers) this.addLayer(layer);
			},
			_addZoomLimit(layer) {
				if (!isNaN(layer.options.maxZoom) || !isNaN(layer.options.minZoom)) {
					this._zoomBoundLayers[stamp(layer)] = layer;
					this._updateZoomLevels();
				}
			},
			_removeZoomLimit(layer) {
				const id = stamp(layer);
				if (this._zoomBoundLayers[id]) {
					delete this._zoomBoundLayers[id];
					this._updateZoomLevels();
				}
			},
			_updateZoomLevels() {
				let minZoom = Infinity, maxZoom = -Infinity;
				const oldZoomSpan = this._getZoomSpan();
				for (const l of Object.values(this._zoomBoundLayers)) {
					const options = l.options;
					minZoom = Math.min(minZoom, options.minZoom ?? Infinity);
					maxZoom = Math.max(maxZoom, options.maxZoom ?? -Infinity);
				}
				this._layersMaxZoom = maxZoom === -Infinity ? void 0 : maxZoom;
				this._layersMinZoom = minZoom === Infinity ? void 0 : minZoom;
				if (oldZoomSpan !== this._getZoomSpan()) this.fire("zoomlevelschange");
				if (this.options.maxZoom === void 0 && this._layersMaxZoom && this.getZoom() > this._layersMaxZoom) this.setZoom(this._layersMaxZoom);
				if (this.options.minZoom === void 0 && this._layersMinZoom && this.getZoom() < this._layersMinZoom) this.setZoom(this._layersMinZoom);
			}
		});
	}
};
//#endregion
//#region src/layer/LayerGroup.js
var LayerGroup = class LayerGroup extends Layer {
	constructor(layers, options) {
		super();
		setOptions(this, options);
		this._layers = {};
		for (const layer of layers ?? []) this.addLayer(layer);
		this.callInitHooks(LayerGroup);
	}
	addLayer(layer) {
		const id = this.getLayerId(layer);
		this._layers[id] = layer;
		this._map?.addLayer(layer);
		return this;
	}
	removeLayer(layer) {
		const id = layer in this._layers ? layer : this.getLayerId(layer);
		if (this._map && this._layers[id]) this._map.removeLayer(this._layers[id]);
		delete this._layers[id];
		return this;
	}
	hasLayer(layer) {
		return (typeof layer === "number" ? layer : this.getLayerId(layer)) in this._layers;
	}
	clearLayers() {
		return this.eachLayer(this.removeLayer, this);
	}
	onAdd(map) {
		this.eachLayer(map.addLayer, map);
	}
	onRemove(map) {
		this.eachLayer(map.removeLayer, map);
	}
	eachLayer(method, context) {
		for (const layer of Object.values(this._layers)) method.call(context, layer);
		return this;
	}
	getLayer(id) {
		return this._layers[id];
	}
	getLayers() {
		const layers = [];
		this.eachLayer(layers.push, layers);
		return layers;
	}
	setZIndex(zIndex) {
		return this.eachLayer((l) => l.setZIndex?.(zIndex));
	}
	getLayerId(layer) {
		return stamp(layer);
	}
};
//#endregion
//#region src/layer/FeatureGroup.js
var FeatureGroup = class FeatureGroup extends LayerGroup {
	constructor(...args) {
		super(...args);
		this.callInitHooks(FeatureGroup);
	}
	addLayer(layer) {
		if (this.hasLayer(layer)) return this;
		layer.addEventParent(this);
		super.addLayer(layer);
		return this.fire("layeradd", { layer });
	}
	removeLayer(layer) {
		if (!this.hasLayer(layer)) return this;
		if (layer in this._layers) layer = this._layers[layer];
		layer.removeEventParent(this);
		super.removeLayer(layer);
		return this.fire("layerremove", { layer });
	}
	setStyle(style) {
		return this.eachLayer((l) => l.setStyle?.(style));
	}
	bringToFront() {
		return this.eachLayer((l) => l.bringToFront?.());
	}
	bringToBack() {
		return this.eachLayer((l) => l.bringToBack?.());
	}
	getBounds() {
		const bounds = new LatLngBounds();
		for (const layer of Object.values(this._layers)) bounds.extend(layer.getBounds ? layer.getBounds() : layer.getLatLng());
		return bounds;
	}
};
//#endregion
//#region src/layer/marker/Icon.js
var Icon = class Icon extends Class {
	static {
		this.setDefaultOptions({
			popupAnchor: [0, 0],
			tooltipAnchor: [0, 0],
			crossOrigin: false
		});
	}
	constructor(options) {
		super();
		setOptions(this, options);
		this.callInitHooks(Icon);
	}
	createIcon(oldIcon) {
		return this._createIcon("icon", oldIcon);
	}
	createShadow(oldIcon) {
		return this._createIcon("shadow", oldIcon);
	}
	_createIcon(name, oldIcon) {
		const src = this._getIconUrl(name);
		if (!src) {
			if (name === "icon") throw new Error("iconUrl not set in Icon options (see the docs).");
			return null;
		}
		const img = this._createImg(src, oldIcon && oldIcon.tagName === "IMG" ? oldIcon : null);
		this._setIconStyles(img, name);
		if (this.options.crossOrigin || this.options.crossOrigin === "") img.crossOrigin = this.options.crossOrigin === true ? "" : this.options.crossOrigin;
		return img;
	}
	_setIconStyles(img, name) {
		const options = this.options;
		let sizeOption = options[`${name}Size`];
		if (typeof sizeOption === "number") sizeOption = [sizeOption, sizeOption];
		const size = Point.validate(sizeOption) && new Point(sizeOption);
		const anchorPosition = name === "shadow" && options.shadowAnchor || options.iconAnchor || size && size.divideBy(2, true);
		const anchor = Point.validate(anchorPosition) && new Point(anchorPosition);
		img.className = `maplair-marker-${name} ${options.className || ""}`;
		if (anchor) {
			img.style.marginLeft = `${-anchor.x}px`;
			img.style.marginTop = `${-anchor.y}px`;
		}
		if (size) {
			img.style.width = `${size.x}px`;
			img.style.height = `${size.y}px`;
		}
	}
	_createImg(src, el) {
		el ??= document.createElement("img");
		el.src = src;
		return el;
	}
	_getIconUrl(name) {
		return Browser_default.retina && this.options[`${name}RetinaUrl`] || this.options[`${name}Url`];
	}
};
//#endregion
//#region src/layer/marker/DefaultIcon.js
const URL_RE = /^url\((['"])?(.+)\1\)$/;
const MARKER_ICON_RE = /^(.*)marker-icon\.svg$/;
var DefaultIcon = class DefaultIcon extends Icon {
	static {
		this.setDefaultOptions({
			iconUrl: "marker-icon.svg",
			iconRetinaUrl: "marker-icon.svg",
			shadowUrl: "marker-shadow.svg",
			iconSize: [25, 41],
			iconAnchor: [12, 41],
			popupAnchor: [1, -34],
			tooltipAnchor: [16, -28],
			shadowSize: [41, 41]
		});
	}
	constructor(...args) {
		super(...args);
		this.callInitHooks(DefaultIcon);
	}
	_getIconUrl(name) {
		if (!DefaultIcon.imagePath) DefaultIcon.imagePath = this._detectIconPath();
		const url = super._getIconUrl(name);
		if (!url) return null;
		return (this.options.imagePath ?? DefaultIcon.imagePath) + url;
	}
	_stripUrl(path) {
		const strip = function(str, re, idx) {
			const match = re.exec(str);
			return match && match[idx];
		};
		path = strip(path, URL_RE, 2);
		return path && strip(path, MARKER_ICON_RE, 1);
	}
	_detectIconPath() {
		const el = create("div", "maplair-default-icon-path", document.body);
		const path = this._stripUrl(getComputedStyle(el).backgroundImage);
		document.body.removeChild(el);
		if (path) return path;
		const link = document.querySelector("link[href$=\"maplair.css\"]");
		if (!link) return "";
		return link.href.substring(0, link.href.length - 11 - 1);
	}
};
//#endregion
//#region src/layer/marker/Marker.Drag.js
var MarkerDrag = class MarkerDrag extends Handler {
	constructor(marker) {
		super(marker._map);
		this._marker = marker;
		this.callInitHooks(MarkerDrag);
	}
	addHooks() {
		const icon = this._marker._icon;
		if (!this._draggable) this._draggable = new Draggable(icon, icon, true);
		this._draggable.on({
			dragstart: this._onDragStart,
			predrag: this._onPreDrag,
			drag: this._onDrag,
			dragend: this._onDragEnd
		}, this).enable();
		icon.classList.add("maplair-marker-draggable");
	}
	removeHooks() {
		this._draggable.off({
			dragstart: this._onDragStart,
			predrag: this._onPreDrag,
			drag: this._onDrag,
			dragend: this._onDragEnd
		}, this).disable();
		this._marker._icon?.classList.remove("maplair-marker-draggable");
	}
	moved() {
		return this._draggable?._moved;
	}
	_adjustPan(e) {
		const marker = this._marker, map = marker._map, speed = this._marker.options.autoPanSpeed, padding = this._marker.options.autoPanPadding, iconPos = getPosition(marker._icon), bounds = map.getPixelBounds(), origin = map.getPixelOrigin();
		const panBounds = new Bounds(bounds.min._subtract(origin).add(padding), bounds.max._subtract(origin).subtract(padding));
		if (!panBounds.contains(iconPos)) {
			const movement = new Point((Math.max(panBounds.max.x, iconPos.x) - panBounds.max.x) / (bounds.max.x - panBounds.max.x) - (Math.min(panBounds.min.x, iconPos.x) - panBounds.min.x) / (bounds.min.x - panBounds.min.x), (Math.max(panBounds.max.y, iconPos.y) - panBounds.max.y) / (bounds.max.y - panBounds.max.y) - (Math.min(panBounds.min.y, iconPos.y) - panBounds.min.y) / (bounds.min.y - panBounds.min.y)).multiplyBy(speed);
			map.panBy(movement, { animate: false });
			this._draggable._newPos._add(movement);
			this._draggable._startPos._add(movement);
			setPosition(marker._icon, this._draggable._newPos);
			this._onDrag(e);
			this._panRequest = requestAnimationFrame(this._adjustPan.bind(this, e));
		}
	}
	_onDragStart() {
		this._oldLatLng = this._marker.getLatLng();
		this._marker.closePopup?.();
		this._marker.fire("movestart").fire("dragstart");
	}
	_onPreDrag(e) {
		if (this._marker.options.autoPan) {
			cancelAnimationFrame(this._panRequest);
			this._panRequest = requestAnimationFrame(this._adjustPan.bind(this, e));
		}
	}
	_onDrag(e) {
		const marker = this._marker, shadow = marker._shadow, iconPos = getPosition(marker._icon), latlng = marker._map.layerPointToLatLng(iconPos);
		if (shadow) setPosition(shadow, iconPos);
		marker._latlng = latlng;
		e.latlng = latlng;
		e.oldLatLng = this._oldLatLng;
		marker.fire("move", e).fire("drag", e);
	}
	_onDragEnd(e) {
		cancelAnimationFrame(this._panRequest);
		delete this._oldLatLng;
		this._marker.fire("moveend").fire("dragend", e);
	}
};
//#endregion
//#region src/layer/marker/Marker.js
var Marker = class Marker extends Layer {
	static {
		this.setDefaultOptions({
			icon: new DefaultIcon(),
			interactive: true,
			keyboard: true,
			title: "",
			alt: "Marker",
			zIndexOffset: 0,
			opacity: 1,
			riseOnHover: false,
			riseOffset: 250,
			pane: "markerPane",
			shadowPane: "shadowPane",
			shadow: true,
			bubblingPointerEvents: false,
			autoPanOnFocus: true,
			draggable: false,
			autoPan: false,
			autoPanPadding: [50, 50],
			autoPanSpeed: 10
		});
	}
	constructor(latlng, options) {
		super();
		setOptions(this, options);
		this._latlng = new LatLng(latlng);
		this.callInitHooks(Marker);
	}
	onAdd(map) {
		this._zoomAnimated = this._zoomAnimated && map.options.markerZoomAnimation;
		if (this._zoomAnimated) map.on("zoomanim", this._animateZoom, this);
		this._initIcon();
		this.update();
		if (map.options.markerCulling) this._updateCulling();
	}
	onRemove(map) {
		if (this.dragging?.enabled()) {
			this.options.draggable = true;
			this.dragging.removeHooks();
		}
		delete this.dragging;
		if (this._zoomAnimated) map.off("zoomanim", this._animateZoom, this);
		this._removeIcon();
		this._removeShadow();
		this._culled = false;
	}
	getEvents() {
		const events = {
			zoom: this.update,
			viewreset: this.update
		};
		if (this._map?.options.markerCulling) events.moveend = this._updateCulling;
		return events;
	}
	getLatLng() {
		return this._latlng;
	}
	setLatLng(latlng) {
		const oldLatLng = this._latlng;
		this._latlng = new LatLng(latlng);
		if (this._map?.options.markerCulling) this._updateCulling();
		this.update();
		return this.fire("move", {
			oldLatLng,
			latlng: this._latlng
		});
	}
	setZIndexOffset(offset) {
		this.options.zIndexOffset = offset;
		return this.update();
	}
	getIcon() {
		return this.options.icon;
	}
	setIcon(icon) {
		this.options.icon = icon;
		if (this._map) {
			this._initIcon();
			this.update();
		}
		if (this._popup) this.bindPopup(this._popup, this._popup.options);
		return this;
	}
	getElement() {
		return this._icon;
	}
	update() {
		if (this._icon && this._map && !this._culled) {
			const pos = this._map.latLngToLayerPoint(this._latlng).round();
			this._setPos(pos);
		}
		return this;
	}
	_initIcon() {
		const options = this.options, classToAdd = `maplair-zoom-${this._zoomAnimated ? "animated" : "hide"}`;
		const icon = options.icon.createIcon(this._icon);
		let addIcon = false;
		if (icon !== this._icon) {
			if (this._icon) this._removeIcon();
			addIcon = true;
			if (options.title) icon.title = options.title;
			if (icon.tagName === "IMG") icon.alt = options.alt ?? "";
		}
		icon.classList.add(classToAdd);
		if (options.keyboard) {
			icon.tabIndex = "0";
			icon.setAttribute("role", "button");
		}
		this._icon = icon;
		if (options.riseOnHover) this.on({
			pointerover: this._bringToFront,
			pointerout: this._resetZIndex
		});
		if (this.options.autoPanOnFocus) on(icon, "focus", this._panOnFocus, this);
		const newShadow = options.shadow ? options.icon.createShadow(this._shadow) : null;
		let addShadow = false;
		if (newShadow !== this._shadow) {
			this._removeShadow();
			addShadow = true;
		}
		if (newShadow) {
			newShadow.classList.add(classToAdd);
			newShadow.alt = "";
		}
		this._shadow = newShadow;
		if (options.opacity < 1) this._updateOpacity();
		if (addIcon) this.getPane().appendChild(this._icon);
		this._initInteraction();
		if (newShadow && addShadow) this.getPane(options.shadowPane).appendChild(this._shadow);
	}
	_removeIcon() {
		if (this.options.riseOnHover) this.off({
			pointerover: this._bringToFront,
			pointerout: this._resetZIndex
		});
		if (this.options.autoPanOnFocus) off(this._icon, "focus", this._panOnFocus, this);
		this._icon.remove();
		this.removeInteractiveTarget(this._icon);
		this._icon = null;
	}
	_updateCulling() {
		if (!this._icon || !this._map) return;
		const visible = this._map.getBounds().pad(.5).contains(this._latlng) || !!this.dragging?._draggable?._moving || this._icon.contains(document.activeElement);
		if (visible === !this._culled) return;
		this._culled = !visible;
		if (visible) {
			this.getPane().appendChild(this._icon);
			if (this._shadow) this.getPane(this.options.shadowPane).appendChild(this._shadow);
			this.update();
		} else {
			this._icon.remove();
			this._shadow?.remove();
		}
	}
	_removeShadow() {
		this._shadow?.remove();
		this._shadow = null;
	}
	_setPos(pos) {
		if (this._icon) setPosition(this._icon, pos);
		if (this._shadow) setPosition(this._shadow, pos);
		this._zIndex = pos.y + this.options.zIndexOffset;
		this._resetZIndex();
	}
	_updateZIndex(offset) {
		const zIndex = String(this._zIndex + offset);
		if (this._icon && this._icon.style.zIndex !== zIndex) this._icon.style.zIndex = zIndex;
	}
	_animateZoom(opt) {
		if (this._culled) return;
		const pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center).round();
		this._setPos(pos);
	}
	_initInteraction() {
		if (!this.options.interactive) return;
		this._icon.classList.add("maplair-interactive");
		this.addInteractiveTarget(this._icon);
		if (MarkerDrag) {
			let draggable = this.options.draggable;
			if (this.dragging) {
				draggable = this.dragging.enabled();
				this.dragging.disable();
			}
			this.dragging = new MarkerDrag(this);
			if (draggable) this.dragging.enable();
		}
	}
	setOpacity(opacity) {
		this.options.opacity = opacity;
		if (this._map) this._updateOpacity();
		return this;
	}
	_updateOpacity() {
		const opacity = this.options.opacity;
		if (this._icon) this._icon.style.opacity = opacity;
		if (this._shadow) this._shadow.style.opacity = opacity;
	}
	_bringToFront() {
		this._updateZIndex(this.options.riseOffset);
	}
	_resetZIndex() {
		this._updateZIndex(0);
	}
	_panOnFocus() {
		const map = this._map;
		if (!map) return;
		const iconOpts = this.options.icon.options;
		const size = iconOpts.iconSize ? new Point(iconOpts.iconSize) : new Point(0, 0);
		const anchor = iconOpts.iconAnchor ? new Point(iconOpts.iconAnchor) : new Point(0, 0);
		map.panInside(this._latlng, {
			paddingTopLeft: anchor,
			paddingBottomRight: size.subtract(anchor)
		});
	}
	_getPopupAnchor() {
		return this.options.icon.options.popupAnchor;
	}
	_getTooltipAnchor() {
		return this.options.icon.options.tooltipAnchor;
	}
};
//#endregion
//#region src/layer/vector/Path.js
var Path = class extends Layer {
	static {
		this.setDefaultOptions({
			stroke: true,
			color: "#3388ff",
			weight: 3,
			opacity: 1,
			lineCap: "round",
			lineJoin: "round",
			dashArray: null,
			dashOffset: null,
			fill: false,
			fillColor: null,
			fillOpacity: .2,
			fillRule: "evenodd",
			interactive: true,
			bubblingPointerEvents: true
		});
	}
	beforeAdd(map) {
		this._renderer = map.getRenderer(this);
	}
	onAdd() {
		this._renderer._initPath(this);
		this._reset();
		this._renderer._addPath(this);
	}
	onRemove() {
		this._renderer._removePath(this);
	}
	redraw() {
		if (this._map) this._renderer._updatePath(this);
		return this;
	}
	setStyle(style) {
		setOptions(this, style);
		if (this._renderer) {
			this._renderer._updateStyle(this);
			if (this.options.stroke && style && Object.hasOwn(style, "weight")) this._updateBounds();
		}
		return this;
	}
	bringToFront() {
		this._renderer?._bringToFront(this);
		return this;
	}
	bringToBack() {
		this._renderer?._bringToBack(this);
		return this;
	}
	getElement() {
		return this._path;
	}
	_reset() {
		this._project();
		this._update();
	}
	_clickTolerance() {
		return (this.options.stroke ? this.options.weight / 2 : 0) + (this._renderer.options.tolerance || 0);
	}
};
//#endregion
//#region src/layer/vector/CircleMarker.js
var CircleMarker = class CircleMarker extends Path {
	static {
		this.setDefaultOptions({
			fill: true,
			radius: 10
		});
	}
	constructor(latlng, options) {
		super();
		setOptions(this, options);
		this._latlng = new LatLng(latlng);
		this._radius = this.options.radius;
		this.callInitHooks(CircleMarker);
	}
	setLatLng(latlng) {
		const oldLatLng = this._latlng;
		this._latlng = new LatLng(latlng);
		this.redraw();
		return this.fire("move", {
			oldLatLng,
			latlng: this._latlng
		});
	}
	getLatLng() {
		return this._latlng;
	}
	setRadius(radius) {
		this.options.radius = this._radius = radius;
		return this.redraw();
	}
	getRadius() {
		return this._radius;
	}
	setStyle(options) {
		super.setStyle(options);
		if (options?.radius !== void 0) this.setRadius(options.radius);
		return this;
	}
	_project() {
		this._point = this._map.latLngToLayerPoint(this._latlng);
		this._pxRadius = this._radius;
		this._updateBounds();
	}
	_updateBounds() {
		const r = this._pxRadius, r2 = this._pxRadiusY ?? r, w = this._clickTolerance(), p = [r + w, r2 + w];
		this._pxBounds = new Bounds(this._point.subtract(p), this._point.add(p));
	}
	_update() {
		if (this._map) this._updatePath();
	}
	_updatePath() {
		this._renderer._updateCircle(this);
	}
	_empty() {
		return this._pxRadius && !this._renderer._bounds.intersects(this._pxBounds);
	}
	_containsPoint(p) {
		return p.distanceTo(this._point) <= this._pxRadius + this._clickTolerance();
	}
};
//#endregion
//#region src/layer/vector/Circle.js
var Circle = class Circle extends CircleMarker {
	constructor(latlng, options) {
		super(latlng, options);
		if (isNaN(this.options.radius)) throw new Error("Circle radius cannot be NaN");
		this.callInitHooks(Circle);
	}
	getBounds() {
		const half = [this._pxRadius, this._pxRadiusY ?? this._pxRadius];
		return new LatLngBounds(this._map.layerPointToLatLng(this._point.subtract(half)), this._map.layerPointToLatLng(this._point.add(half)));
	}
	_project() {
		const lng = this._latlng.lng, lat = this._latlng.lat, map = this._map, crs = map.options.crs;
		if (crs.distance === EarthCRS.distance) {
			const d = Math.PI / 180, latR = this._radius / EarthCRS.R / d, top = map.project([lat + latR, lng]), bottom = map.project([lat - latR, lng]), p = top.add(bottom).divideBy(2), lat2 = map.unproject(p).lat;
			let lngR = Math.acos((Math.cos(latR * d) - Math.sin(lat * d) * Math.sin(lat2 * d)) / (Math.cos(lat * d) * Math.cos(lat2 * d))) / d;
			if (isNaN(lngR) || lngR === 0) lngR = latR / Math.cos(Math.PI / 180 * lat);
			this._point = p.subtract(map.getPixelOrigin());
			this._pxRadius = isNaN(lngR) ? 0 : p.x - map.project([lat2, lng - lngR]).x;
			this._pxRadiusY = p.y - top.y;
		} else {
			const latlng2 = crs.unproject(crs.project(this._latlng).subtract([this._radius, 0]));
			this._point = map.latLngToLayerPoint(this._latlng);
			this._pxRadius = Math.abs(this._point.x - map.latLngToLayerPoint(latlng2).x);
		}
		this._updateBounds();
	}
};
//#endregion
//#region src/layer/vector/Polyline.js
var Polyline = class Polyline extends Path {
	static {
		this.setDefaultOptions({
			smoothFactor: .5,
			noClip: false
		});
	}
	constructor(latlngs, options) {
		super();
		setOptions(this, options);
		this._setLatLngs(latlngs);
		this.callInitHooks(Polyline);
	}
	getLatLngs() {
		return this._latlngs;
	}
	setLatLngs(latlngs) {
		this._setLatLngs(latlngs);
		return this.redraw();
	}
	isEmpty() {
		return !this._latlngs.length;
	}
	closestLayerPoint(p) {
		p = new Point(p);
		let minDistance = Infinity, minPoint = null, p1, p2;
		const closest = _sqClosestPointOnSegment;
		for (const points of this._parts) for (let i = 1, len = points.length; i < len; i++) {
			p1 = points[i - 1];
			p2 = points[i];
			const sqDist = closest(p, p1, p2, true);
			if (sqDist < minDistance) {
				minDistance = sqDist;
				minPoint = closest(p, p1, p2);
			}
		}
		if (minPoint) minPoint.distance = Math.sqrt(minDistance);
		return minPoint;
	}
	getCenter() {
		if (!this._map) throw new Error("Must add layer to map before using getCenter()");
		return polylineCenter(this._defaultShape(), this._map.options.crs);
	}
	getBounds() {
		return this._bounds;
	}
	addLatLng(latlng, latlngs) {
		latlngs ??= this._defaultShape();
		latlng = new LatLng(latlng);
		latlngs.push(latlng);
		this._bounds.extend(latlng);
		return this.redraw();
	}
	_setLatLngs(latlngs) {
		this._bounds = new LatLngBounds();
		this._latlngs = this._convertLatLngs(latlngs);
	}
	_defaultShape() {
		return isFlat(this._latlngs) ? this._latlngs : this._latlngs[0];
	}
	_convertLatLngs(latlngs) {
		const result = [], flat = isFlat(latlngs);
		for (let i = 0, len = latlngs.length; i < len; i++) if (flat) {
			result[i] = new LatLng(latlngs[i]);
			this._bounds.extend(result[i]);
		} else result[i] = this._convertLatLngs(latlngs[i]);
		return result;
	}
	_project() {
		const pxBounds = new Bounds();
		this._rings = [];
		this._projectLatlngs(this._latlngs, this._rings, pxBounds);
		if (this._bounds.isValid() && pxBounds.isValid()) {
			this._rawPxBounds = pxBounds;
			this._updateBounds();
		}
	}
	_updateBounds() {
		const w = this._clickTolerance(), p = new Point(w, w);
		if (!this._rawPxBounds) return;
		this._pxBounds = new Bounds([this._rawPxBounds.min.subtract(p), this._rawPxBounds.max.add(p)]);
	}
	_projectLatlngs(latlngs, result, projectedBounds) {
		if (latlngs[0] instanceof LatLng) {
			const ring = latlngs.map((latlng) => this._map.latLngToLayerPoint(latlng));
			ring.forEach((r) => projectedBounds.extend(r));
			result.push(ring);
		} else latlngs.forEach((latlng) => this._projectLatlngs(latlng, result, projectedBounds));
	}
	_clipPoints() {
		const bounds = this._renderer._bounds;
		this._parts = [];
		if (!this._pxBounds || !this._pxBounds.intersects(bounds)) return;
		if (this.options.noClip) {
			this._parts = this._rings;
			return;
		}
		const parts = this._parts;
		let i, j, k, len, len2, segment, points;
		for (i = 0, k = 0, len = this._rings.length; i < len; i++) {
			points = this._rings[i];
			for (j = 0, len2 = points.length; j < len2 - 1; j++) {
				segment = clipSegment(points[j], points[j + 1], bounds, j, true);
				if (!segment) continue;
				parts[k] ??= [];
				parts[k].push(segment[0]);
				if (segment[1] !== points[j + 1] || j === len2 - 2) {
					parts[k].push(segment[1]);
					k++;
				}
			}
		}
	}
	_simplifyPoints() {
		const parts = this._parts, tolerance = this.options.smoothFactor;
		for (let i = 0, len = parts.length; i < len; i++) parts[i] = simplify(parts[i], tolerance);
	}
	_update() {
		if (!this._map) return;
		this._clipPoints();
		this._simplifyPoints();
		this._updatePath();
	}
	_updatePath() {
		this._renderer._updatePoly(this);
	}
	_containsPoint(p, closed) {
		let i, j, k, len, len2, part;
		const w = this._clickTolerance();
		if (!this._pxBounds || !this._pxBounds.contains(p)) return false;
		for (i = 0, len = this._parts.length; i < len; i++) {
			part = this._parts[i];
			for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) {
				if (!closed && j === 0) continue;
				if (pointToSegmentDistance(p, part[k], part[j]) <= w) return true;
			}
		}
		return false;
	}
};
//#endregion
//#region src/layer/vector/Polygon.js
var Polygon = class Polygon extends Polyline {
	static {
		this.setDefaultOptions({ fill: true });
	}
	constructor(...args) {
		super(...args);
		this.callInitHooks(Polygon);
	}
	isEmpty() {
		return !this._latlngs.length || !this._latlngs[0].length;
	}
	getCenter() {
		if (!this._map) throw new Error("Must add layer to map before using getCenter()");
		return polygonCenter(this._defaultShape(), this._map.options.crs);
	}
	_convertLatLngs(latlngs) {
		const result = super._convertLatLngs(latlngs), len = result.length;
		if (len >= 2 && result[0] instanceof LatLng && result[0].equals(result[len - 1])) result.pop();
		return result;
	}
	_setLatLngs(latlngs) {
		super._setLatLngs(latlngs);
		if (isFlat(this._latlngs)) this._latlngs = [this._latlngs];
	}
	_defaultShape() {
		return isFlat(this._latlngs[0]) ? this._latlngs[0] : this._latlngs[0][0];
	}
	_clipPoints() {
		let bounds = this._renderer._bounds;
		const w = this.options.weight, p = new Point(w, w);
		bounds = new Bounds(bounds.min.subtract(p), bounds.max.add(p));
		this._parts = [];
		if (!this._pxBounds || !this._pxBounds.intersects(bounds)) return;
		if (this.options.noClip) {
			this._parts = this._rings;
			return;
		}
		for (const ring of this._rings) {
			const clipped = clipPolygon(ring, bounds, true);
			if (clipped.length) this._parts.push(clipped);
		}
	}
	_updatePath() {
		this._renderer._updatePoly(this, true);
	}
	_containsPoint(p) {
		let inside = false, part, p1, p2, i, j, k, len, len2;
		if (!this._pxBounds || !this._pxBounds.contains(p)) return false;
		for (i = 0, len = this._parts.length; i < len; i++) {
			part = this._parts[i];
			for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) {
				p1 = part[j];
				p2 = part[k];
				if (p1.y > p.y !== p2.y > p.y && p.x < (p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x) inside = !inside;
			}
		}
		return inside || super._containsPoint(p, true);
	}
};
//#endregion
//#region src/layer/GeoJSON.js
var GeoJSON = class GeoJSON extends FeatureGroup {
	constructor(geojson, options) {
		super(void 0, options);
		if (geojson) this.addData(geojson);
		this.callInitHooks(GeoJSON);
	}
	addData(geojson) {
		const features = Array.isArray(geojson) ? geojson : geojson.features;
		if (features) {
			for (const feature of features) if (feature.geometries || feature.geometry || feature.features || feature.coordinates) this.addData(feature);
			return this;
		}
		const options = this.options;
		if (options.filter && !options.filter(geojson)) return this;
		const layer = GeoJSON.geometryToLayer(geojson, options);
		if (!layer) return this;
		layer.feature = GeoJSON.asFeature(geojson);
		layer.defaultOptions = layer.options;
		this.resetStyle(layer);
		if (options.onEachFeature) options.onEachFeature(geojson, layer);
		return this.addLayer(layer);
	}
	resetStyle(layer) {
		if (layer === void 0) return this.eachLayer(this.resetStyle, this);
		layer.options = Object.create(layer.defaultOptions);
		this._setLayerStyle(layer, this.options.style);
		return this;
	}
	setStyle(style) {
		return this.eachLayer((layer) => this._setLayerStyle(layer, style));
	}
	_setLayerStyle(layer, style) {
		if (layer.setStyle) {
			if (typeof style === "function") style = style(layer.feature);
			layer.setStyle(style);
		}
	}
	static geometryToLayer(geojson, options) {
		const geometry = geojson.type === "Feature" ? geojson.geometry : geojson, coords = geometry?.coordinates, layers = [], pointToLayer = options?.pointToLayer, _coordsToLatLng = options?.coordsToLatLng ?? GeoJSON.coordsToLatLng;
		let latlng, latlngs;
		if (!coords && !geometry) return null;
		switch (geometry.type) {
			case "Point":
				latlng = _coordsToLatLng(coords);
				return GeoJSON._pointToLayer(pointToLayer, geojson, latlng, options);
			case "MultiPoint":
				for (const coord of coords) {
					latlng = _coordsToLatLng(coord);
					layers.push(GeoJSON._pointToLayer(pointToLayer, geojson, latlng, options));
				}
				return new FeatureGroup(layers);
			case "LineString":
			case "MultiLineString":
				latlngs = GeoJSON.coordsToLatLngs(coords, geometry.type === "LineString" ? 0 : 1, _coordsToLatLng);
				return new Polyline(latlngs, options);
			case "Polygon":
			case "MultiPolygon":
				latlngs = GeoJSON.coordsToLatLngs(coords, geometry.type === "Polygon" ? 1 : 2, _coordsToLatLng);
				return new Polygon(latlngs, options);
			case "GeometryCollection":
				for (const g of geometry.geometries) {
					const geoLayer = GeoJSON.geometryToLayer({
						geometry: g,
						type: "Feature",
						properties: geojson.properties
					}, options);
					if (geoLayer) layers.push(geoLayer);
				}
				return new FeatureGroup(layers);
			case "FeatureCollection":
				for (const f of geometry.features) {
					const featureLayer = GeoJSON.geometryToLayer(f, options);
					if (featureLayer) layers.push(featureLayer);
				}
				return new FeatureGroup(layers);
			default: throw new Error("Invalid GeoJSON object.");
		}
	}
	static _pointToLayer(pointToLayerFn, geojson, latlng, options) {
		return pointToLayerFn ? pointToLayerFn(geojson, latlng) : new Marker(latlng, options?.markersInheritOptions && options);
	}
	static coordsToLatLng(coords) {
		return new LatLng(coords[1], coords[0], coords[2]);
	}
	static coordsToLatLngs(coords, levelsDeep, _coordsToLatLng) {
		return coords.map((coord) => levelsDeep ? GeoJSON.coordsToLatLngs(coord, levelsDeep - 1, _coordsToLatLng) : (_coordsToLatLng || GeoJSON.coordsToLatLng)(coord));
	}
	static latLngToCoords(latlng, precision) {
		latlng = new LatLng(latlng);
		return latlng.alt !== void 0 ? [
			formatNum(latlng.lng, precision),
			formatNum(latlng.lat, precision),
			formatNum(latlng.alt, precision)
		] : [formatNum(latlng.lng, precision), formatNum(latlng.lat, precision)];
	}
	static latLngsToCoords(latlngs, levelsDeep, close, precision) {
		const coords = latlngs.map((latlng) => levelsDeep ? GeoJSON.latLngsToCoords(latlng, isFlat(latlng) ? 0 : levelsDeep - 1, close, precision) : GeoJSON.latLngToCoords(latlng, precision));
		if (!levelsDeep && close && coords.length > 0) coords.push(coords[0].slice());
		return coords;
	}
	static getFeature(layer, newGeometry) {
		return layer.feature ? {
			...layer.feature,
			geometry: newGeometry
		} : GeoJSON.asFeature(newGeometry);
	}
	static asFeature(geojson) {
		if (geojson.type === "Feature" || geojson.type === "FeatureCollection") return geojson;
		return {
			type: "Feature",
			properties: {},
			geometry: geojson
		};
	}
};
const PointToGeoJSON = { toGeoJSON(precision) {
	return GeoJSON.getFeature(this, {
		type: "Point",
		coordinates: GeoJSON.latLngToCoords(this.getLatLng(), precision)
	});
} };
Marker.include(PointToGeoJSON);
Circle.include(PointToGeoJSON);
CircleMarker.include(PointToGeoJSON);
Polyline.include({ toGeoJSON(precision) {
	const multi = !isFlat(this._latlngs);
	const coords = GeoJSON.latLngsToCoords(this._latlngs, multi ? 1 : 0, false, precision);
	return GeoJSON.getFeature(this, {
		type: `${multi ? "Multi" : ""}LineString`,
		coordinates: coords
	});
} });
Polygon.include({ toGeoJSON(precision) {
	const holes = !isFlat(this._latlngs), multi = holes && !isFlat(this._latlngs[0]);
	let coords = GeoJSON.latLngsToCoords(this._latlngs, multi ? 2 : holes ? 1 : 0, true, precision);
	if (!holes) coords = [coords];
	return GeoJSON.getFeature(this, {
		type: `${multi ? "Multi" : ""}Polygon`,
		coordinates: coords
	});
} });
LayerGroup.include({
	toMultiPoint(precision) {
		const coords = [];
		this.eachLayer((layer) => {
			coords.push(layer.toGeoJSON(precision).geometry.coordinates);
		});
		return GeoJSON.getFeature(this, {
			type: "MultiPoint",
			coordinates: coords
		});
	},
	toGeoJSON(precision) {
		const type = this.feature?.geometry?.type;
		if (type === "MultiPoint") return this.toMultiPoint(precision);
		const isGeometryCollection = type === "GeometryCollection", jsons = [];
		this.eachLayer((layer) => {
			if (layer.toGeoJSON) {
				const json = layer.toGeoJSON(precision);
				if (isGeometryCollection) jsons.push(json.geometry);
				else {
					const feature = GeoJSON.asFeature(json);
					if (feature.type === "FeatureCollection") jsons.push(...feature.features);
					else jsons.push(feature);
				}
			}
		});
		if (isGeometryCollection) return GeoJSON.getFeature(this, {
			geometries: jsons,
			type: "GeometryCollection"
		});
		return {
			type: "FeatureCollection",
			features: jsons
		};
	}
});
//#endregion
//#region src/layer/BlanketOverlay.js
var BlanketOverlay = class BlanketOverlay extends Layer {
	static {
		this.setDefaultOptions({
			padding: .1,
			continuous: false
		});
	}
	constructor(options) {
		super();
		setOptions(this, options);
		this.callInitHooks(BlanketOverlay);
	}
	onAdd() {
		if (!this._container) {
			this._initContainer();
			this._container.classList.add("maplair-zoom-animated");
		}
		this.getPane().appendChild(this._container);
		this._resizeContainer();
		this._onMoveEnd();
	}
	onRemove() {
		this._destroyContainer();
	}
	getEvents() {
		const events = {
			viewreset: this._reset,
			zoom: this._onZoom,
			moveend: this._onMoveEnd,
			resize: this._resizeContainer,
			zoomend: this._onZoomEnd
		};
		if (this._zoomAnimated) events.zoomanim = this._onAnimZoom;
		if (this.options.continuous) events.move = this._onMoveEnd;
		return events;
	}
	_onAnimZoom(ev) {
		this._updateTransform(ev.center, ev.zoom);
	}
	_onZoom() {
		this._updateTransform(this._map.getCenter(), this._map.getZoom());
	}
	_updateTransform(center, zoom) {
		const scale = this._map.getZoomScale(zoom, this._zoom), viewHalf = this._map.getSize().multiplyBy(.5 + this.options.padding), currentCenterPoint = this._map.project(this._center, zoom), topLeftOffset = viewHalf.multiplyBy(-scale)._add(currentCenterPoint)._subtract(this._map._getNewPixelOrigin(center, zoom))._round();
		setTransform(this._container, topLeftOffset, scale);
	}
	_onMoveEnd(ev) {
		const p = this.options.padding, size = this._map.getSize(), min = this._map.containerPointToLayerPoint(size.multiplyBy(-p)).round();
		this._bounds = new Bounds(min, min.add(size.multiplyBy(1 + p * 2)).round());
		this._center = this._map.getCenter();
		this._zoom = this._map.getZoom();
		this._updateTransform(this._center, this._zoom);
		this._onSettled(ev);
	}
	_reset() {
		this._onSettled();
		this._updateTransform(this._center, this._zoom);
		this._onViewReset();
	}
	_initContainer() {
		this._container = create("div");
	}
	_destroyContainer() {
		off(this._container);
		this._container.remove();
		delete this._container;
	}
	_resizeContainer() {
		const p = this.options.padding, size = this._map.getSize().multiplyBy(1 + p * 2).round();
		this._container.style.width = `${size.x}px`;
		this._container.style.height = `${size.y}px`;
		return size;
	}
	_onZoomEnd() {}
	_onViewReset() {}
	_onSettled() {}
};
//#endregion
//#region src/layer/ImageOverlay.js
var ImageOverlay = class ImageOverlay extends Layer {
	static {
		this.setDefaultOptions({
			opacity: 1,
			alt: "",
			interactive: false,
			crossOrigin: false,
			errorOverlayUrl: "",
			zIndex: 1,
			className: "",
			decoding: "auto"
		});
	}
	constructor(url, bounds, options) {
		super();
		this._url = url;
		this._bounds = new LatLngBounds(bounds);
		setOptions(this, options);
		this.callInitHooks(ImageOverlay);
	}
	onAdd() {
		if (!this._image) {
			this._initImage();
			if (this.options.opacity < 1) this._updateOpacity();
		}
		if (this.options.interactive) {
			this._image.classList.add("maplair-interactive");
			this.addInteractiveTarget(this._image);
		}
		this.getPane().appendChild(this._image);
		this._reset();
	}
	onRemove() {
		this._image.remove();
		if (this.options.interactive) this.removeInteractiveTarget(this._image);
	}
	setOpacity(opacity) {
		this.options.opacity = opacity;
		if (this._image) this._updateOpacity();
		return this;
	}
	setStyle(styleOpts) {
		if (styleOpts.opacity) this.setOpacity(styleOpts.opacity);
		return this;
	}
	bringToFront() {
		if (this._map) toFront(this._image);
		return this;
	}
	bringToBack() {
		if (this._map) toBack(this._image);
		return this;
	}
	setUrl(url) {
		this._url = url;
		if (this._image) this._image.src = url;
		return this;
	}
	setBounds(bounds) {
		this._bounds = new LatLngBounds(bounds);
		if (this._map) this._reset();
		return this;
	}
	getEvents() {
		const events = {
			zoom: this._reset,
			viewreset: this._reset
		};
		if (this._zoomAnimated) events.zoomanim = this._animateZoom;
		return events;
	}
	setZIndex(value) {
		this.options.zIndex = value;
		this._updateZIndex();
		return this;
	}
	getBounds() {
		return this._bounds;
	}
	getElement() {
		return this._image;
	}
	_initImage() {
		const wasElementSupplied = this._url.tagName === "IMG";
		const img = this._image = wasElementSupplied ? this._url : create("img");
		img.classList.add("maplair-image-layer");
		if (this._zoomAnimated) img.classList.add("maplair-zoom-animated");
		if (this.options.className) img.classList.add(...splitWords(this.options.className));
		img.onselectstart = falseFn;
		img.onpointermove = falseFn;
		img.onload = this.fire.bind(this, "load");
		img.onerror = this._overlayOnError.bind(this);
		if (this.options.crossOrigin || this.options.crossOrigin === "") img.crossOrigin = this.options.crossOrigin === true ? "" : this.options.crossOrigin;
		img.decoding = this.options.decoding;
		if (this.options.zIndex) this._updateZIndex();
		if (wasElementSupplied) {
			this._url = img.src;
			return;
		}
		img.src = this._url;
		img.alt = this.options.alt;
	}
	_animateZoom(e) {
		const scale = this._map.getZoomScale(e.zoom), offset = this._map._latLngBoundsToNewLayerBounds(this._bounds, e.zoom, e.center).min;
		setTransform(this._image, offset, scale);
	}
	_reset() {
		const image = this._image, bounds = new Bounds(this._map.latLngToLayerPoint(this._bounds.getNorthWest()), this._map.latLngToLayerPoint(this._bounds.getSouthEast())), size = bounds.getSize();
		setPosition(image, bounds.min);
		image.style.width = `${size.x}px`;
		image.style.height = `${size.y}px`;
	}
	_updateOpacity() {
		this._image.style.opacity = this.options.opacity;
	}
	_updateZIndex() {
		if (this._image && this.options.zIndex !== void 0 && this.options.zIndex !== null) this._image.style.zIndex = this.options.zIndex;
	}
	_overlayOnError() {
		this.fire("error");
		const errorUrl = this.options.errorOverlayUrl;
		if (errorUrl && this._url !== errorUrl) {
			this._url = errorUrl;
			this._image.src = errorUrl;
		}
	}
	getCenter() {
		return this._bounds.getCenter();
	}
};
//#endregion
//#region src/layer/VideoOverlay.js
var VideoOverlay = class VideoOverlay extends ImageOverlay {
	static {
		this.setDefaultOptions({
			autoplay: true,
			controls: false,
			loop: true,
			keepAspectRatio: true,
			muted: false,
			playsInline: true
		});
	}
	constructor(...args) {
		super(...args);
		this.callInitHooks(VideoOverlay);
	}
	_initImage() {
		const wasElementSupplied = this._url.tagName === "VIDEO";
		const vid = this._image = wasElementSupplied ? this._url : create("video");
		vid.classList.add("maplair-image-layer");
		if (this._zoomAnimated) vid.classList.add("maplair-zoom-animated");
		if (this.options.className) vid.classList.add(...splitWords(this.options.className));
		on(vid, "pointerdown", (e) => {
			if (vid.controls) stopPropagation(e);
		});
		vid.onloadeddata = this.fire.bind(this, "load");
		if (wasElementSupplied) {
			const sourceElements = vid.getElementsByTagName("source");
			const sources = sourceElements.map((e) => e.src);
			this._url = sourceElements.length > 0 ? sources : [vid.src];
			return;
		}
		if (!Array.isArray(this._url)) this._url = [this._url];
		if (!this.options.keepAspectRatio && Object.hasOwn(vid.style, "objectFit")) vid.style["objectFit"] = "fill";
		vid.autoplay = !!this.options.autoplay;
		vid.controls = !!this.options.controls;
		vid.loop = !!this.options.loop;
		vid.muted = !!this.options.muted;
		vid.playsInline = !!this.options.playsInline;
		for (const url of this._url) {
			const source = create("source");
			source.src = url;
			vid.appendChild(source);
		}
	}
};
//#endregion
//#region src/layer/SVGOverlay.js
var SVGOverlay = class SVGOverlay extends ImageOverlay {
	constructor(...args) {
		super(...args);
		this.callInitHooks(SVGOverlay);
	}
	_initImage() {
		const el = this._image = this._url;
		el.classList.add("maplair-image-layer");
		if (this._zoomAnimated) el.classList.add("maplair-zoom-animated");
		if (this.options.className) el.classList.add(...splitWords(this.options.className));
		el.onselectstart = falseFn;
		el.onpointermove = falseFn;
	}
};
//#endregion
//#region src/layer/DivOverlay.js
var DivOverlay = class DivOverlay extends Layer {
	static {
		this.setDefaultOptions({
			interactive: false,
			offset: [0, 0],
			className: "",
			pane: void 0,
			content: ""
		});
	}
	constructor(options, source) {
		super();
		if (options instanceof LatLng || Array.isArray(options)) {
			this._latlng = new LatLng(options);
			setOptions(this, source);
		} else {
			setOptions(this, options);
			this._source = source;
		}
		if (this.options.content) this._content = this.options.content;
		this.callInitHooks(DivOverlay);
	}
	openOn(map) {
		map = arguments.length ? map : this._source._map;
		if (!map.hasLayer(this)) map.addLayer(this);
		return this;
	}
	close() {
		this._map?.removeLayer(this);
		return this;
	}
	toggle(layer) {
		if (this._map) this.close();
		else {
			if (arguments.length) this._source = layer;
			else layer = this._source;
			this._prepareOpen();
			this.openOn(layer._map);
		}
		return this;
	}
	onAdd(map) {
		this._zoomAnimated = map._zoomAnimated;
		if (!this._container) this._initLayout();
		if (map._fadeAnimated) this._container.style.opacity = 0;
		clearTimeout(this._removeTimeout);
		this.getPane().appendChild(this._container);
		this.update();
		if (map._fadeAnimated) this._container.style.opacity = 1;
		this.bringToFront();
		if (this.options.interactive) {
			this._container.classList.add("maplair-interactive");
			this.addInteractiveTarget(this._container);
		}
	}
	onRemove(map) {
		if (map._fadeAnimated) {
			this._container.style.opacity = 0;
			this._removeTimeout = setTimeout(() => this._container.remove(), 200);
		} else this._container.remove();
		if (this.options.interactive) {
			this._container.classList.remove("maplair-interactive");
			this.removeInteractiveTarget(this._container);
		}
	}
	getLatLng() {
		return this._latlng;
	}
	setLatLng(latlng) {
		this._latlng = new LatLng(latlng);
		if (this._map) {
			this._updatePosition();
			this._adjustPan();
		}
		return this;
	}
	getContent() {
		return this._content;
	}
	setContent(content) {
		this._content = content;
		this.update();
		return this;
	}
	getElement() {
		return this._container;
	}
	update() {
		if (!this._map) return;
		this._container.style.visibility = "hidden";
		this._updateContent();
		this._updateLayout();
		this._updatePosition();
		this._container.style.visibility = "";
		this._adjustPan();
	}
	getEvents() {
		const events = {
			zoom: this._updatePosition,
			viewreset: this._updatePosition
		};
		if (this._zoomAnimated) events.zoomanim = this._animateZoom;
		return events;
	}
	isOpen() {
		return !!this._map && this._map.hasLayer(this);
	}
	bringToFront() {
		if (this._map) toFront(this._container);
		return this;
	}
	bringToBack() {
		if (this._map) toBack(this._container);
		return this;
	}
	_prepareOpen(latlng) {
		let source = this._source;
		if (!source._map) return false;
		if (source instanceof FeatureGroup) {
			source = null;
			for (const layer of Object.values(this._source._layers)) if (layer._map) {
				source = layer;
				break;
			}
			if (!source) return false;
			this._source = source;
		}
		if (!latlng) {
			if (source.getCenter) latlng = source.getCenter();
			else if (source.getLatLng) latlng = source.getLatLng();
			else if (source.getBounds) latlng = source.getBounds().getCenter();
			else throw new Error("Unable to get source layer LatLng.");
		}
		this.setLatLng(latlng);
		if (this._map) this.update();
		return true;
	}
	_updateContent() {
		if (!this._content) return;
		const node = this._contentNode;
		const content = typeof this._content === "function" ? this._content(this._source ?? this) : this._content;
		if (typeof content === "string") node.innerHTML = content;
		else {
			while (node.hasChildNodes()) node.removeChild(node.firstChild);
			node.appendChild(content);
		}
		this.fire("contentupdate");
	}
	_updatePosition() {
		if (!this._map) return;
		const pos = this._map.latLngToLayerPoint(this._latlng), anchor = this._getAnchor();
		let offset = new Point(this.options.offset);
		if (this._zoomAnimated) setPosition(this._container, pos.add(anchor));
		else offset = offset.add(pos).add(anchor);
		const bottom = this._containerBottom = -offset.y, left = this._containerLeft = -Math.round(this._containerWidth / 2) + offset.x;
		this._container.style.bottom = `${bottom}px`;
		this._container.style.left = `${left}px`;
	}
	_getAnchor() {
		return [0, 0];
	}
	static register(MaplairMap) {
		MaplairMap.include({ _initOverlay(OverlayClass, content, latlng, options) {
			let overlay = content;
			if (!(overlay instanceof OverlayClass)) overlay = new OverlayClass(options).setContent(content);
			if (latlng) overlay.setLatLng(latlng);
			return overlay;
		} });
		Layer.include({ _initOverlay(OverlayClass, old, content, options) {
			let overlay = content;
			if (overlay instanceof OverlayClass) {
				setOptions(overlay, options);
				overlay._source = this;
			} else {
				overlay = old && !options ? old : new OverlayClass(options, this);
				overlay.setContent(content);
			}
			return overlay;
		} });
	}
};
//#endregion
//#region src/layer/Popup.js
var Popup = class Popup extends DivOverlay {
	static {
		this.setDefaultOptions({
			pane: "popupPane",
			offset: [0, 7],
			maxWidth: 300,
			minWidth: 50,
			maxHeight: null,
			autoPan: !Browser_default.reducedMotion,
			autoPanPaddingTopLeft: null,
			autoPanPaddingBottomRight: null,
			autoPanPadding: [5, 5],
			keepInView: false,
			closeButton: true,
			autoClose: true,
			closeOnEscapeKey: true,
			className: "",
			trackResize: true
		});
	}
	constructor(...args) {
		super(...args);
		this.callInitHooks(Popup);
	}
	openOn(map) {
		map = arguments.length ? map : this._source._map;
		if (!map.hasLayer(this) && map._popup && map._popup.options.autoClose) map.removeLayer(map._popup);
		map._popup = this;
		return super.openOn(map);
	}
	onAdd(map) {
		super.onAdd(map);
		map.fire("popupopen", { popup: this });
		if (this._source) {
			this._source.fire("popupopen", { popup: this }, true);
			if (!(this._source instanceof Path)) this._source.on("preclick", stopPropagation);
		}
	}
	onRemove(map) {
		super.onRemove(map);
		map.fire("popupclose", { popup: this });
		if (this._source) {
			this._source.fire("popupclose", { popup: this }, true);
			if (!(this._source instanceof Path)) this._source.off("preclick", stopPropagation);
		}
	}
	getEvents() {
		const events = super.getEvents();
		if (this.options.closeOnClick ?? this._map.options.closePopupOnClick) events.preclick = this.close;
		if (this.options.keepInView) events.moveend = this._adjustPan;
		return events;
	}
	_initLayout() {
		const prefix = "maplair-popup", container = this._container = create("div", `${prefix} ${this.options.className || ""} maplair-zoom-animated`);
		const wrapper = this._wrapper = create("div", `${prefix}-content-wrapper`, container);
		this._contentNode = create("div", `${prefix}-content`, wrapper);
		disableClickPropagation(container);
		disableScrollPropagation(this._contentNode);
		on(container, "contextmenu", stopPropagation);
		this._tipContainer = create("div", `${prefix}-tip-container`, container);
		this._tip = create("div", `${prefix}-tip`, this._tipContainer);
		if (this.options.closeButton) {
			const closeButton = this._closeButton = create("a", `${prefix}-close-button`, container);
			closeButton.setAttribute("role", "button");
			closeButton.setAttribute("aria-label", I18n.translate("Close popup"));
			closeButton.href = "#close";
			closeButton.innerHTML = "<span aria-hidden=\"true\">&#215;</span>";
			on(closeButton, "click", (ev) => {
				ev.preventDefault();
				this.close();
			});
		}
		if (this.options.trackResize) {
			this._resizeObserver = new ResizeObserver(((entries) => {
				if (!this._map) return;
				this._containerWidth = entries[0]?.contentRect?.width;
				this._containerHeight = entries[0]?.contentRect?.height;
				this._updateLayout();
				this._updatePosition();
				this._adjustPan();
			}));
			this._resizeObserver.observe(this._contentNode);
		}
	}
	_updateLayout() {
		const container = this._contentNode, style = container.style;
		style.maxWidth = `${this.options.maxWidth}px`;
		style.minWidth = `${this.options.minWidth}px`;
		const maxHeight = this.options.maxHeight, scrolledClass = "maplair-popup-scrolled";
		if (maxHeight && (this._containerHeight ?? container.offsetHeight) > maxHeight) {
			style.height = `${maxHeight}px`;
			container.classList.add(scrolledClass);
		} else container.classList.remove(scrolledClass);
		this._containerWidth = this._container.offsetWidth;
		this._containerHeight = this._container.offsetHeight;
		this._containerMarginBottom = parseInt(getComputedStyle(this._container).marginBottom, 10) || 0;
	}
	_animateZoom(e) {
		const pos = this._map._latLngToNewLayerPoint(this._latlng, e.zoom, e.center), anchor = this._getAnchor();
		setPosition(this._container, pos.add(anchor));
	}
	_adjustPan() {
		if (!this.options.autoPan) return;
		this._map._panAnim?.stop();
		if (this._autopanning) {
			this._autopanning = false;
			return;
		}
		const map = this._map, marginBottom = this._containerMarginBottom ?? (parseInt(getComputedStyle(this._container).marginBottom, 10) || 0), containerHeight = this._containerHeight + marginBottom, containerWidth = this._containerWidth, layerPos = new Point(this._containerLeft, -containerHeight - this._containerBottom);
		layerPos._add(getPosition(this._container));
		const containerPos = map.layerPointToContainerPoint(layerPos), padding = new Point(this.options.autoPanPadding), paddingTL = new Point(this.options.autoPanPaddingTopLeft ?? padding), paddingBR = new Point(this.options.autoPanPaddingBottomRight ?? padding), size = map.getSize();
		let dx = 0, dy = 0;
		if (containerPos.x + containerWidth + paddingBR.x > size.x) dx = containerPos.x + containerWidth - size.x + paddingBR.x;
		if (containerPos.x - dx - paddingTL.x < 0) dx = containerPos.x - paddingTL.x;
		if (containerPos.y + containerHeight + paddingBR.y > size.y) dy = containerPos.y + containerHeight - size.y + paddingBR.y;
		if (containerPos.y - dy - paddingTL.y < 0) dy = containerPos.y - paddingTL.y;
		if (dx || dy) {
			if (this.options.keepInView) this._autopanning = true;
			map.fire("autopanstart").panBy([dx, dy]);
		}
	}
	_getAnchor() {
		return new Point(this._source?._getPopupAnchor ? this._source._getPopupAnchor() : [0, 0]);
	}
	static register(MaplairMap) {
		MaplairMap.mergeOptions({ closePopupOnClick: true });
		MaplairMap.include({
			openPopup(popup, latlng, options) {
				this._initOverlay(Popup, popup, latlng, options).openOn(this);
				return this;
			},
			closePopup(popup) {
				popup = arguments.length ? popup : this._popup;
				popup?.close();
				return this;
			}
		});
		Layer.include({
			bindPopup(content, options) {
				this._popup = this._initOverlay(Popup, this._popup, content, options);
				if (!this._popupHandlersAdded) {
					this.on({
						click: this._openPopup,
						keypress: this._onKeyPress,
						remove: this.closePopup,
						move: this._movePopup
					});
					this._popupHandlersAdded = true;
				}
				return this;
			},
			unbindPopup() {
				if (this._popup) {
					this.off({
						click: this._openPopup,
						keypress: this._onKeyPress,
						remove: this.closePopup,
						move: this._movePopup
					});
					this._popupHandlersAdded = false;
					this._popup = null;
				}
				return this;
			},
			openPopup(latlng) {
				if (this._popup) {
					if (!(this instanceof FeatureGroup)) this._popup._source = this;
					if (this._popup._prepareOpen(latlng || this._latlng)) this._popup.openOn(this._map);
				}
				return this;
			},
			closePopup() {
				this._popup?.close();
				return this;
			},
			togglePopup() {
				this._popup?.toggle(this);
				return this;
			},
			isPopupOpen() {
				return this._popup?.isOpen() ?? false;
			},
			setPopupContent(content) {
				this._popup?.setContent(content);
				return this;
			},
			getPopup() {
				return this._popup;
			},
			_openPopup(e) {
				if (!this._popup || !this._map) return;
				stop(e);
				const target = e.propagatedFrom ?? e.target;
				if (this._popup._source === target && !(target instanceof Path)) {
					if (this._map.hasLayer(this._popup)) this.closePopup();
					else this.openPopup(e.latlng);
					return;
				}
				this._popup._source = target;
				this.openPopup(e.latlng);
			},
			_movePopup(e) {
				this._popup.setLatLng(e.latlng);
			},
			_onKeyPress(e) {
				if (e.originalEvent.code === "Enter") this._openPopup(e);
			}
		});
	}
};
//#endregion
//#region src/layer/Tooltip.js
var Tooltip = class Tooltip extends DivOverlay {
	static {
		this.setDefaultOptions({
			pane: "tooltipPane",
			offset: [0, 0],
			direction: "auto",
			permanent: false,
			sticky: false,
			opacity: .9
		});
	}
	constructor(...args) {
		super(...args);
		this.callInitHooks(Tooltip);
	}
	onAdd(map) {
		super.onAdd(map);
		this.setOpacity(this.options.opacity);
		map.fire("tooltipopen", { tooltip: this });
		if (this._source) {
			this.addEventParent(this._source);
			this._source.fire("tooltipopen", { tooltip: this }, true);
		}
	}
	onRemove(map) {
		super.onRemove(map);
		map.fire("tooltipclose", { tooltip: this });
		if (this._source) {
			this.removeEventParent(this._source);
			this._source.fire("tooltipclose", { tooltip: this }, true);
		}
	}
	getEvents() {
		const events = super.getEvents();
		if (!this.options.permanent) events.preclick = this.close;
		return events;
	}
	_initLayout() {
		const className = `maplair-tooltip ${this.options.className || ""} maplair-zoom-${this._zoomAnimated ? "animated" : "hide"}`;
		this._contentNode = this._container = create("div", className);
		this._container.setAttribute("role", "tooltip");
		this._container.setAttribute("id", `maplair-tooltip-${stamp(this)}`);
	}
	_updateLayout() {}
	_adjustPan() {}
	_setPosition(pos) {
		let subX, subY, direction = this.options.direction;
		const map = this._map, container = this._container, centerPoint = map.latLngToContainerPoint(map.getCenter()), tooltipPoint = map.layerPointToContainerPoint(pos), tooltipWidth = container.offsetWidth, tooltipHeight = container.offsetHeight, offset = new Point(this.options.offset), anchor = this._getAnchor();
		if (direction === "top") {
			subX = tooltipWidth / 2;
			subY = tooltipHeight;
		} else if (direction === "bottom") {
			subX = tooltipWidth / 2;
			subY = 0;
		} else if (direction === "center") {
			subX = tooltipWidth / 2;
			subY = tooltipHeight / 2;
		} else if (direction === "right") {
			subX = 0;
			subY = tooltipHeight / 2;
		} else if (direction === "left") {
			subX = tooltipWidth;
			subY = tooltipHeight / 2;
		} else if (tooltipPoint.x < centerPoint.x) {
			direction = "right";
			subX = 0;
			subY = tooltipHeight / 2;
		} else {
			direction = "left";
			subX = tooltipWidth + (offset.x + anchor.x) * 2;
			subY = tooltipHeight / 2;
		}
		pos = pos.subtract(new Point(subX, subY, true)).add(offset).add(anchor);
		container.classList.remove("maplair-tooltip-right", "maplair-tooltip-left", "maplair-tooltip-top", "maplair-tooltip-bottom");
		container.classList.add(`maplair-tooltip-${direction}`);
		setPosition(container, pos);
	}
	_updatePosition() {
		const pos = this._map.latLngToLayerPoint(this._latlng);
		this._setPosition(pos);
	}
	setOpacity(opacity) {
		this.options.opacity = opacity;
		if (this._container) this._container.style.opacity = opacity;
	}
	_animateZoom(e) {
		const pos = this._map._latLngToNewLayerPoint(this._latlng, e.zoom, e.center);
		this._setPosition(pos);
	}
	_getAnchor() {
		return new Point(this._source?._getTooltipAnchor && !this.options.sticky ? this._source._getTooltipAnchor() : [0, 0]);
	}
	static register(MaplairMap) {
		MaplairMap.include({
			openTooltip(tooltip, latlng, options) {
				this._initOverlay(Tooltip, tooltip, latlng, options).openOn(this);
				return this;
			},
			closeTooltip(tooltip) {
				tooltip.close();
				return this;
			}
		});
		Layer.include({
			bindTooltip(content, options) {
				if (this._tooltip && this.isTooltipOpen()) this.unbindTooltip();
				this._tooltip = this._initOverlay(Tooltip, this._tooltip, content, options);
				this._initTooltipInteractions();
				if (this._tooltip.options.permanent && this._map && this._map.hasLayer(this)) this.openTooltip();
				return this;
			},
			unbindTooltip() {
				if (this._tooltip) {
					this._initTooltipInteractions(true);
					this.closeTooltip();
					this._tooltip = null;
				}
				return this;
			},
			_initTooltipInteractions(remove) {
				if (!remove && this._tooltipHandlersAdded) return;
				const onOff = remove ? "off" : "on", events = {
					remove: this.closeTooltip,
					move: this._moveTooltip
				};
				if (!this._tooltip.options.permanent) {
					events.pointerover = this._openTooltip;
					events.pointerout = this.closeTooltip;
					events.click = this._openTooltip;
					if (this._map) this._addFocusListeners(remove);
					else events.add = () => this._addFocusListeners(remove);
				} else events.add = this._openTooltip;
				if (this._tooltip.options.sticky) events.pointermove = this._moveTooltip;
				this[onOff](events);
				this._tooltipHandlersAdded = !remove;
			},
			openTooltip(latlng) {
				if (this._tooltip) {
					if (!(this instanceof FeatureGroup)) this._tooltip._source = this;
					if (this._tooltip._prepareOpen(latlng)) {
						this._tooltip.openOn(this._map);
						if (this.getElement) this._setAriaDescribedByOnLayer(this);
						else if (this.eachLayer) this.eachLayer(this._setAriaDescribedByOnLayer, this);
					}
				}
				return this;
			},
			closeTooltip() {
				if (this._tooltip) return this._tooltip.close();
			},
			toggleTooltip() {
				this._tooltip?.toggle(this);
				return this;
			},
			isTooltipOpen() {
				return this._tooltip.isOpen();
			},
			setTooltipContent(content) {
				this._tooltip?.setContent(content);
				return this;
			},
			getTooltip() {
				return this._tooltip;
			},
			_addFocusListeners(remove) {
				if (this.getElement) this._addFocusListenersOnLayer(this, remove);
				else if (this.eachLayer) this.eachLayer((layer) => this._addFocusListenersOnLayer(layer, remove), this);
			},
			_addFocusListenersOnLayer(layer, remove) {
				const el = typeof layer.getElement === "function" && layer.getElement();
				if (el) {
					const toggle = remove ? off : on;
					if (!remove) {
						el._maplair_focus_handler && off(el, "focus", el._maplair_focus_handler, this);
						el._maplair_focus_handler = () => {
							if (this._tooltip) {
								this._tooltip._source = layer;
								this.openTooltip();
							}
						};
					}
					el._maplair_focus_handler && toggle(el, "focus", el._maplair_focus_handler, this);
					toggle(el, "blur", this.closeTooltip, this);
					if (remove) delete el._maplair_focus_handler;
				}
			},
			_setAriaDescribedByOnLayer(layer) {
				(typeof layer.getElement === "function" && layer.getElement())?.setAttribute?.("aria-describedby", this._tooltip._container.id);
			},
			_openTooltip(e) {
				if (!this._tooltip || !this._map) return;
				if (this._map.dragging?.moving()) {
					if (e.type === "add" && !this._moveEndOpensTooltip) {
						this._moveEndOpensTooltip = true;
						this._map.once("moveend", () => {
							this._moveEndOpensTooltip = false;
							this._openTooltip(e);
						});
					}
					return;
				}
				this._tooltip._source = e.propagatedFrom ?? e.target;
				this.openTooltip(this._tooltip.options.sticky ? e.latlng : void 0);
			},
			_moveTooltip(e) {
				let latlng = e.latlng, containerPoint, layerPoint;
				if (this._tooltip.options.sticky && e.originalEvent) {
					containerPoint = this._map.pointerEventToContainerPoint(e.originalEvent);
					layerPoint = this._map.containerPointToLayerPoint(containerPoint);
					latlng = this._map.layerPointToLatLng(layerPoint);
				}
				this._tooltip.setLatLng(latlng);
			}
		});
	}
};
//#endregion
//#region src/layer/marker/DivIcon.js
var DivIcon = class DivIcon extends Icon {
	static {
		this.setDefaultOptions({
			iconSize: [12, 12],
			html: false,
			bgPos: null,
			className: "maplair-div-icon"
		});
	}
	constructor(...args) {
		super(...args);
		this.callInitHooks(DivIcon);
	}
	createIcon(oldIcon) {
		const div = oldIcon && oldIcon.tagName === "DIV" ? oldIcon : document.createElement("div"), options = this.options;
		if (options.html instanceof Element) {
			div.replaceChildren();
			div.appendChild(options.html);
		} else div.innerHTML = options.html !== false ? options.html : "";
		if (options.bgPos) {
			const bgPos = new Point(options.bgPos);
			div.style.backgroundPosition = `${-bgPos.x}px ${-bgPos.y}px`;
		}
		this._setIconStyles(div, "icon");
		return div;
	}
	createShadow() {
		return null;
	}
};
//#endregion
//#region src/layer/tile/GridLayer.js
var GridLayer = class GridLayer extends Layer {
	static {
		this.setDefaultOptions({
			tileSize: 256,
			opacity: 1,
			updateWhenIdle: !Browser_default.reducedMotion,
			updateWhenZooming: true,
			updateInterval: Browser_default.reducedMotion ? 5e3 : 200,
			zIndex: 1,
			bounds: null,
			minZoom: 0,
			maxZoom: void 0,
			maxNativeZoom: void 0,
			minNativeZoom: void 0,
			noWrap: false,
			pane: "tilePane",
			className: "",
			keepBuffer: 2
		});
	}
	constructor(options) {
		super();
		setOptions(this, options);
		this.callInitHooks(GridLayer);
	}
	onAdd() {
		this._initContainer();
		this._levels = {};
		this._tiles = {};
		this._resetView();
	}
	beforeAdd(map) {
		map._addZoomLimit(this);
	}
	onRemove(map) {
		this._removeAllTiles();
		this._container.remove();
		map._removeZoomLimit(this);
		this._container = null;
		this._tileZoom = void 0;
		clearTimeout(this._pruneTimeout);
	}
	bringToFront() {
		if (this._map) {
			toFront(this._container);
			this._setAutoZIndex(Math.max);
		}
		return this;
	}
	bringToBack() {
		if (this._map) {
			toBack(this._container);
			this._setAutoZIndex(Math.min);
		}
		return this;
	}
	getContainer() {
		return this._container;
	}
	setOpacity(opacity) {
		this.options.opacity = opacity;
		this._updateOpacity();
		return this;
	}
	setZIndex(zIndex) {
		this.options.zIndex = zIndex;
		this._updateZIndex();
		return this;
	}
	isLoading() {
		return this._loading;
	}
	redraw() {
		if (this._map) {
			this._removeAllTiles();
			const tileZoom = this._clampZoom(this._map.getZoom());
			if (tileZoom !== this._tileZoom) {
				this._tileZoom = tileZoom;
				this._updateLevels();
			}
			this._update();
		}
		return this;
	}
	getEvents() {
		const events = {
			viewprereset: this._invalidateAll,
			viewreset: this._resetView,
			zoom: this._resetView,
			moveend: this._onMoveEnd
		};
		if (!this.options.updateWhenIdle) {
			if (!this._onMove) this._onMove = throttle(this._onMoveEnd, this.options.updateInterval, this);
			events.move = this._onMove;
		}
		if (this._zoomAnimated) events.zoomanim = this._animateZoom;
		return events;
	}
	createTile() {
		return document.createElement("div");
	}
	getTileSize() {
		const s = this.options.tileSize;
		return s instanceof Point ? s : new Point(s, s);
	}
	_updateZIndex() {
		if (this._container && this.options.zIndex !== void 0 && this.options.zIndex !== null) this._container.style.zIndex = this.options.zIndex;
	}
	_setAutoZIndex(compare) {
		const layers = this.getPane().children;
		let edgeZIndex = -compare(-Infinity, Infinity);
		for (const layer of layers) {
			const zIndex = layer.style.zIndex;
			if (layer !== this._container && zIndex) edgeZIndex = compare(edgeZIndex, +zIndex);
		}
		if (isFinite(edgeZIndex)) {
			this.options.zIndex = edgeZIndex + compare(-1, 1);
			this._updateZIndex();
		}
	}
	_updateOpacity() {
		if (!this._map) return;
		this._container.style.opacity = this.options.opacity;
		const now = Date.now();
		let nextFrame = false, willPrune = false;
		for (const tile of Object.values(this._tiles ?? {})) {
			if (!tile.current || !tile.loaded) continue;
			const fade = Math.min(1, (now - tile.loaded) / 200);
			tile.el.style.opacity = fade;
			if (fade < 1) nextFrame = true;
			else {
				if (tile.active) willPrune = true;
				else this._onOpaqueTile(tile);
				tile.active = true;
			}
		}
		if (willPrune && !this._noPrune) this._pruneTiles();
		if (nextFrame) {
			cancelAnimationFrame(this._fadeFrame);
			this._fadeFrame = requestAnimationFrame(this._updateOpacity.bind(this));
		}
	}
	_onOpaqueTile() {}
	_initContainer() {
		if (this._container) return;
		this._container = create("div", `maplair-layer ${this.options.className ?? ""}`);
		this._updateZIndex();
		if (this.options.opacity < 1) this._updateOpacity();
		this.getPane().appendChild(this._container);
	}
	_updateLevels() {
		const zoom = this._tileZoom, maxZoom = this.options.maxZoom;
		if (zoom === void 0) return;
		for (let z of Object.keys(this._levels)) {
			z = Number(z);
			if (this._levels[z].el.children.length || z === zoom) {
				this._levels[z].el.style.zIndex = maxZoom - Math.abs(zoom - z);
				this._onUpdateLevel(z);
			} else {
				this._levels[z].el.remove();
				this._removeTilesAtZoom(z);
				this._onRemoveLevel(z);
				delete this._levels[z];
			}
		}
		let level = this._levels[zoom];
		const map = this._map;
		if (!level) {
			level = this._levels[zoom] = {};
			level.el = create("div", "maplair-tile-container maplair-zoom-animated", this._container);
			level.el.style.zIndex = maxZoom;
			level.origin = map.project(map.unproject(map.getPixelOrigin()), zoom).round();
			level.zoom = zoom;
			this._setZoomTransform(level, map.getCenter(), map.getZoom());
			level.el.offsetWidth;
			this._onCreateLevel(level);
		}
		this._level = level;
		return level;
	}
	_onUpdateLevel() {}
	_onRemoveLevel() {}
	_onCreateLevel() {}
	_pruneTiles() {
		if (!this._map) return;
		const zoom = this._map.getZoom();
		if (zoom > this.options.maxZoom || zoom < this.options.minZoom) {
			this._removeAllTiles();
			return;
		}
		for (const tile of Object.values(this._tiles)) tile.retain = tile.current;
		for (const tile of Object.values(this._tiles)) if (tile.current && !tile.active) {
			const coords = tile.coords;
			if (!this._retainParent(coords.x, coords.y, coords.z, coords.z - 5)) this._retainChildren(coords.x, coords.y, coords.z, coords.z + 2);
		}
		for (const [key, tile] of Object.entries(this._tiles)) if (!tile.retain) this._removeTile(key);
	}
	_removeTilesAtZoom(zoom) {
		for (const [key, tile] of Object.entries(this._tiles)) if (tile.coords.z === zoom) this._removeTile(key);
	}
	_removeAllTiles() {
		for (const key of Object.keys(this._tiles)) this._removeTile(key);
	}
	_invalidateAll() {
		for (const z of Object.keys(this._levels)) {
			this._levels[z].el.remove();
			this._onRemoveLevel(Number(z));
			delete this._levels[z];
		}
		this._removeAllTiles();
		this._tileZoom = void 0;
	}
	_retainParent(x, y, z, minZoom) {
		const x2 = Math.floor(x / 2), y2 = Math.floor(y / 2), z2 = z - 1, coords2 = new Point(+x2, +y2);
		coords2.z = +z2;
		const key = this._tileCoordsToKey(coords2), tile = this._tiles[key];
		if (tile?.active) {
			tile.retain = true;
			return true;
		} else if (tile?.loaded) tile.retain = true;
		if (z2 > minZoom) return this._retainParent(x2, y2, z2, minZoom);
		return false;
	}
	_retainChildren(x, y, z, maxZoom) {
		for (let i = 2 * x; i < 2 * x + 2; i++) for (let j = 2 * y; j < 2 * y + 2; j++) {
			const coords = new Point(i, j);
			coords.z = z + 1;
			const key = this._tileCoordsToKey(coords), tile = this._tiles[key];
			if (tile?.active) {
				tile.retain = true;
				continue;
			} else if (tile?.loaded) tile.retain = true;
			if (z + 1 < maxZoom) this._retainChildren(i, j, z + 1, maxZoom);
		}
	}
	_resetView(e) {
		const animating = e && (e.pinch || e.flyTo);
		this._setView(this._map.getCenter(), this._map.getZoom(), animating, animating);
	}
	_animateZoom(e) {
		this._setView(e.center, e.zoom, true, e.noUpdate);
	}
	_clampZoom(zoom) {
		const options = this.options;
		if (void 0 !== options.minNativeZoom && zoom < options.minNativeZoom) return options.minNativeZoom;
		if (void 0 !== options.maxNativeZoom && options.maxNativeZoom < zoom) return options.maxNativeZoom;
		return zoom;
	}
	_setView(center, zoom, noPrune, noUpdate) {
		let tileZoom = Math.round(zoom);
		if (this.options.maxZoom !== void 0 && tileZoom > this.options.maxZoom || this.options.minZoom !== void 0 && tileZoom < this.options.minZoom) tileZoom = void 0;
		else tileZoom = this._clampZoom(tileZoom);
		const tileZoomChanged = this.options.updateWhenZooming && tileZoom !== this._tileZoom;
		if (!noUpdate || tileZoomChanged) {
			this._tileZoom = tileZoom;
			if (this._abortLoading) this._abortLoading();
			this._updateLevels();
			this._resetGrid();
			if (tileZoom !== void 0) this._update(center);
			if (!noPrune) this._pruneTiles();
			this._noPrune = !!noPrune;
		}
		this._setZoomTransforms(center, zoom);
	}
	_setZoomTransforms(center, zoom) {
		for (const level of Object.values(this._levels)) this._setZoomTransform(level, center, zoom);
	}
	_setZoomTransform(level, center, zoom) {
		const scale = this._map.getZoomScale(zoom, level.zoom), translate = level.origin.multiplyBy(scale).subtract(this._map._getNewPixelOrigin(center, zoom)).round();
		setTransform(level.el, translate, scale);
	}
	_resetGrid() {
		const map = this._map, crs = map.options.crs, tileSize = this._tileSize = this.getTileSize(), tileZoom = this._tileZoom;
		const bounds = this._map.getPixelWorldBounds(this._tileZoom);
		if (bounds) this._globalTileRange = this._pxBoundsToTileRange(bounds);
		this._wrapX = crs.wrapLng && !this.options.noWrap && [Math.floor(map.project([0, crs.wrapLng[0]], tileZoom).x / tileSize.x), Math.ceil(map.project([0, crs.wrapLng[1]], tileZoom).x / tileSize.y)];
		this._wrapY = crs.wrapLat && !this.options.noWrap && [Math.floor(map.project([crs.wrapLat[0], 0], tileZoom).y / tileSize.x), Math.ceil(map.project([crs.wrapLat[1], 0], tileZoom).y / tileSize.y)];
	}
	_onMoveEnd() {
		if (!this._map || this._map._animatingZoom) return;
		this._update();
	}
	_getTiledPixelBounds(center) {
		const map = this._map, mapZoom = map._animatingZoom ? Math.max(map._animateToZoom, map.getZoom()) : map.getZoom(), scale = map.getZoomScale(mapZoom, this._tileZoom), pixelCenter = map.project(center, this._tileZoom).floor(), halfSize = map.getSize().divideBy(scale * 2);
		return new Bounds(pixelCenter.subtract(halfSize), pixelCenter.add(halfSize));
	}
	_update(center) {
		const map = this._map;
		if (!map) return;
		const zoom = this._clampZoom(map.getZoom());
		if (center === void 0) center = map.getCenter();
		if (this._tileZoom === void 0) return;
		const pixelBounds = this._getTiledPixelBounds(center), tileRange = this._pxBoundsToTileRange(pixelBounds), tileCenter = tileRange.getCenter(), queue = [], margin = this.options.keepBuffer, noPruneRange = new Bounds(tileRange.getBottomLeft().subtract([margin, -margin]), tileRange.getTopRight().add([margin, -margin]));
		if (!(isFinite(tileRange.min.x) && isFinite(tileRange.min.y) && isFinite(tileRange.max.x) && isFinite(tileRange.max.y))) throw new Error("Attempted to load an infinite number of tiles");
		for (const tile of Object.values(this._tiles)) {
			const c = tile.coords;
			if (c.z !== this._tileZoom || !noPruneRange.contains(new Point(c.x, c.y))) tile.current = false;
		}
		if (Math.abs(zoom - this._tileZoom) > 1) {
			this._setView(center, zoom);
			return;
		}
		for (let j = tileRange.min.y; j <= tileRange.max.y; j++) for (let i = tileRange.min.x; i <= tileRange.max.x; i++) {
			const coords = new Point(i, j);
			coords.z = this._tileZoom;
			if (!this._isValidTile(coords)) continue;
			const tile = this._tiles[this._tileCoordsToKey(coords)];
			if (tile) tile.current = true;
			else queue.push(coords);
		}
		queue.sort((a, b) => a.distanceTo(tileCenter) - b.distanceTo(tileCenter));
		if (queue.length !== 0) {
			if (!this._loading) {
				this._loading = true;
				this.fire("loading");
			}
			const fragment = document.createDocumentFragment();
			for (const q of queue) this._addTile(q, fragment);
			this._level.el.appendChild(fragment);
		}
	}
	_isValidTile(coords) {
		const crs = this._map.options.crs;
		if (!crs.infinite) {
			const bounds = this._globalTileRange;
			if (!crs.wrapLng && (coords.x < bounds.min.x || coords.x > bounds.max.x) || !crs.wrapLat && (coords.y < bounds.min.y || coords.y > bounds.max.y)) return false;
		}
		if (!this.options.bounds) return true;
		const tileBounds = this._tileCoordsToBounds(coords);
		return new LatLngBounds(this.options.bounds).overlaps(tileBounds);
	}
	_keyToBounds(key) {
		return this._tileCoordsToBounds(this._keyToTileCoords(key));
	}
	_tileCoordsToNwSe(coords) {
		const map = this._map, tileSize = this.getTileSize(), nwPoint = coords.scaleBy(tileSize), sePoint = nwPoint.add(tileSize);
		return [map.unproject(nwPoint, coords.z), map.unproject(sePoint, coords.z)];
	}
	_tileCoordsToBounds(coords) {
		const bp = this._tileCoordsToNwSe(coords);
		let bounds = new LatLngBounds(bp[0], bp[1]);
		if (!this.options.noWrap) bounds = this._map.wrapLatLngBounds(bounds);
		return bounds;
	}
	_tileCoordsToKey(coords) {
		return `${coords.x}:${coords.y}:${coords.z}`;
	}
	_keyToTileCoords(key) {
		const k = key.split(":"), coords = new Point(+k[0], +k[1]);
		coords.z = +k[2];
		return coords;
	}
	_removeTile(key) {
		const tile = this._tiles[key];
		if (!tile) return;
		tile.el.remove();
		delete this._tiles[key];
		this.fire("tileunload", {
			tile: tile.el,
			coords: this._keyToTileCoords(key)
		});
	}
	_initTile(tile) {
		tile.classList.add("maplair-tile");
		const tileSize = this.getTileSize();
		tile.style.width = `${tileSize.x}px`;
		tile.style.height = `${tileSize.y}px`;
		tile.onselectstart = falseFn;
		tile.onpointermove = falseFn;
	}
	_addTile(coords, container) {
		const tilePos = this._getTilePos(coords), key = this._tileCoordsToKey(coords);
		const tile = this.createTile(this._wrapCoords(coords), this._tileReady.bind(this, coords));
		this._initTile(tile);
		if (this.createTile.length < 2) requestAnimationFrame(this._tileReady.bind(this, coords, null, tile));
		setPosition(tile, tilePos);
		this._tiles[key] = {
			el: tile,
			coords,
			current: true
		};
		container.appendChild(tile);
		this.fire("tileloadstart", {
			tile,
			coords
		});
	}
	_tileReady(coords, err, tile) {
		if (err) this.fire("tileerror", {
			error: err,
			tile,
			coords
		});
		const key = this._tileCoordsToKey(coords);
		tile = this._tiles[key];
		if (!tile) return;
		tile.loaded = Date.now();
		if (this._map._fadeAnimated) {
			tile.el.style.opacity = 0;
			cancelAnimationFrame(this._fadeFrame);
			this._fadeFrame = requestAnimationFrame(this._updateOpacity.bind(this));
		} else {
			tile.active = true;
			this._pruneTiles();
		}
		if (!err) {
			tile.el.classList.add("maplair-tile-loaded");
			this.fire("tileload", {
				tile: tile.el,
				coords
			});
		}
		if (this._noTilesToLoad()) {
			this._loading = false;
			this.fire("load");
			if (!this._map._fadeAnimated) requestAnimationFrame(this._pruneTiles.bind(this));
			else this._pruneTimeout = setTimeout(this._pruneTiles.bind(this), 250);
		}
	}
	_getTilePos(coords) {
		return coords.scaleBy(this.getTileSize()).subtract(this._level.origin);
	}
	_wrapCoords(coords) {
		const newCoords = new Point(this._wrapX ? wrapNum(coords.x, this._wrapX) : coords.x, this._wrapY ? wrapNum(coords.y, this._wrapY) : coords.y);
		newCoords.z = coords.z;
		return newCoords;
	}
	_pxBoundsToTileRange(bounds) {
		const tileSize = this.getTileSize();
		return new Bounds(bounds.min.unscaleBy(tileSize).floor(), bounds.max.unscaleBy(tileSize).ceil().subtract([1, 1]));
	}
	_noTilesToLoad() {
		return Object.values(this._tiles).every((t) => t.loaded);
	}
};
//#endregion
//#region src/layer/tile/TileLayer.js
var TileLayer = class TileLayer extends GridLayer {
	static {
		this.setDefaultOptions({
			minZoom: 0,
			maxZoom: 18,
			subdomains: "abc",
			errorTileUrl: "",
			zoomOffset: 0,
			tms: false,
			zoomReverse: false,
			detectRetina: false,
			crossOrigin: false,
			referrerPolicy: "strict-origin-when-cross-origin"
		});
	}
	constructor(url, options) {
		super(options);
		this._url = url;
		options = setOptions(this, options);
		const tileUrl = new URL(this._url, location.href);
		const urlHostname = tileUrl.hostname;
		if (["tile.openstreetmap.org", "tile.osm.org"].some((host) => urlHostname.endsWith(host))) {
			if (options.attribution === null) options.attribution = `&copy; <a href="https://www.openstreetmap.org/copyright">${I18n.translate("OpenStreetMap contributors")}</a>`;
			if (tileUrl.protocol === "http:") {
				tileUrl.protocol = "https:";
				this._url = tileUrl.toString();
			}
		}
		if (this.options.detectRetina && Browser_default.retina && this.options.maxZoom > 0) {
			this.options.tileSize = Math.floor(this.options.tileSize / 2);
			if (!this.options.zoomReverse) {
				this.options.zoomOffset++;
				this.options.maxZoom = Math.max(this.options.minZoom, this.options.maxZoom - 1);
			} else {
				this.options.zoomOffset--;
				this.options.minZoom = Math.min(this.options.maxZoom, this.options.minZoom + 1);
			}
			this.options.minZoom = Math.max(0, this.options.minZoom);
		} else if (!this.options.zoomReverse) this.options.maxZoom = Math.max(this.options.minZoom, this.options.maxZoom);
		else this.options.minZoom = Math.min(this.options.maxZoom, this.options.minZoom);
		if (typeof this.options.subdomains === "string") this.options.subdomains = this.options.subdomains.split("");
		this.on("tileunload", this._onTileRemove);
		this.callInitHooks(TileLayer);
	}
	setUrl(url, noRedraw) {
		if (this._url === url && noRedraw === void 0) noRedraw = true;
		this._url = url;
		if (!noRedraw) this.redraw();
		return this;
	}
	createTile(coords, done) {
		const tile = document.createElement("img");
		on(tile, "load", this._tileOnLoad.bind(this, done, tile));
		on(tile, "error", this._tileOnError.bind(this, done, tile));
		if (this.options.crossOrigin || this.options.crossOrigin === "") tile.crossOrigin = this.options.crossOrigin === true ? "" : this.options.crossOrigin;
		if (typeof this.options.referrerPolicy === "string") tile.referrerPolicy = this.options.referrerPolicy;
		tile.alt = "";
		tile.src = this.getTileUrl(coords);
		return tile;
	}
	getTileUrl(coords) {
		const data = Object.create(this.options);
		Object.assign(data, {
			r: Browser_default.retina ? "@2x" : "",
			s: this._getSubdomain(coords),
			x: coords.x,
			y: coords.y,
			z: this._getZoomForUrl()
		});
		if (this._map && !this._map.options.crs.infinite) {
			const invertedY = this._globalTileRange.max.y - coords.y;
			if (this.options.tms) data["y"] = invertedY;
			data["-y"] = invertedY;
		}
		return template(this._url, data);
	}
	_tileOnLoad(done, tile) {
		done(null, tile);
	}
	_tileOnError(done, tile, e) {
		const errorUrl = this.options.errorTileUrl;
		if (errorUrl && tile.getAttribute("src") !== errorUrl) tile.src = errorUrl;
		done(e, tile);
	}
	_onTileRemove(e) {
		e.tile.onload = null;
	}
	_getZoomForUrl() {
		let zoom = this._tileZoom;
		const maxZoom = this.options.maxZoom, zoomReverse = this.options.zoomReverse, zoomOffset = this.options.zoomOffset;
		if (zoomReverse) zoom = maxZoom - zoom;
		return zoom + zoomOffset;
	}
	_getSubdomain(tilePoint) {
		const index = Math.abs(tilePoint.x + tilePoint.y) % this.options.subdomains.length;
		return this.options.subdomains[index];
	}
	_abortLoading() {
		let i, tile;
		for (i of Object.keys(this._tiles)) if (this._tiles[i].coords.z !== this._tileZoom) {
			tile = this._tiles[i].el;
			tile.onload = falseFn;
			tile.onerror = falseFn;
			if (!tile.complete) {
				tile.setAttribute("src", "");
				const coords = this._tiles[i].coords;
				tile.remove();
				delete this._tiles[i];
				this.fire("tileabort", {
					tile,
					coords
				});
			}
		}
	}
	_removeTile(key) {
		const tile = this._tiles[key];
		if (!tile) return;
		tile.el.setAttribute("src", "");
		return super._removeTile(key);
	}
	_tileReady(coords, err, tile) {
		if (!this._map || tile && tile.getAttribute("src") === "") return;
		return super._tileReady(coords, err, tile);
	}
	_clampZoom(zoom) {
		return Math.round(super._clampZoom(zoom));
	}
};
//#endregion
//#region src/layer/tile/WMSTileLayer.js
var WMSTileLayer = class WMSTileLayer extends TileLayer {
	static {
		this.prototype.defaultWmsParams = {
			service: "WMS",
			request: "GetMap",
			layers: "",
			styles: "",
			format: "image/jpeg",
			transparent: false,
			version: "1.1.1"
		};
		this.setDefaultOptions({
			crs: null,
			uppercase: false
		});
	}
	constructor(url, options) {
		super(url, options);
		const wmsParams = { ...this.defaultWmsParams };
		for (const [key, value] of Object.entries(options)) if (!(key in WMSTileLayer.prototype.options)) wmsParams[key] = value;
		const realRetina = this.options.detectRetina && Browser_default.retina ? 2 : 1;
		const tileSize = this.getTileSize();
		wmsParams.width = tileSize.x * realRetina;
		wmsParams.height = tileSize.y * realRetina;
		this.wmsParams = wmsParams;
		this.callInitHooks(WMSTileLayer);
	}
	onAdd(map) {
		this._crs = this.options.crs ?? map.options.crs;
		this._wmsVersion = parseFloat(this.wmsParams.version);
		const projectionKey = this._wmsVersion >= 1.3 ? "crs" : "srs";
		this.wmsParams[projectionKey] = this._crs.code;
		super.onAdd(map);
	}
	getTileUrl(coords) {
		const tileBounds = this._tileCoordsToNwSe(coords), crs = this._crs, bounds = new Bounds(crs.project(tileBounds[0]), crs.project(tileBounds[1])), min = bounds.min, max = bounds.max, bbox = (this._wmsVersion >= 1.3 && this._crs === EPSG4326 ? [
			min.y,
			min.x,
			max.y,
			max.x
		] : [
			min.x,
			min.y,
			max.x,
			max.y
		]).join(",");
		const url = new URL(super.getTileUrl(coords));
		for (const [k, v] of Object.entries({
			...this.wmsParams,
			bbox
		})) url.searchParams.append(this.options.uppercase ? k.toUpperCase() : k, v);
		return url.toString();
	}
	setParams(params, noRedraw) {
		Object.assign(this.wmsParams, params);
		if (!noRedraw) this.redraw();
		return this;
	}
};
//#endregion
//#region src/layer/vector/Renderer.js
var Renderer = class Renderer extends BlanketOverlay {
	constructor(options) {
		super({
			...options,
			continuous: false
		});
		stamp(this);
		this._layers ??= {};
		this.callInitHooks(Renderer);
	}
	onAdd(map) {
		super.onAdd(map);
		this.on("update", this._updatePaths, this);
	}
	onRemove() {
		super.onRemove();
		this.off("update", this._updatePaths, this);
	}
	_onZoomEnd() {
		for (const layer of Object.values(this._layers)) layer._project();
	}
	_updatePaths() {
		for (const layer of Object.values(this._layers)) layer._update();
	}
	_onViewReset() {
		for (const layer of Object.values(this._layers)) layer._reset();
	}
	_onSettled() {
		this._update();
	}
	_update() {}
};
//#endregion
//#region src/layer/vector/Canvas.js
const DASH_SEPARATOR_RE = /[, ]+/;
var Canvas = class Canvas extends Renderer {
	static {
		this.setDefaultOptions({ tolerance: 0 });
	}
	constructor(...args) {
		super(...args);
		this.callInitHooks(Canvas);
	}
	getEvents() {
		const events = super.getEvents();
		events.viewprereset = this._onViewPreReset;
		return events;
	}
	_onViewPreReset() {
		this._postponeUpdatePaths = true;
	}
	onAdd(map) {
		super.onAdd(map);
		this._draw();
	}
	onRemove() {
		super.onRemove();
		clearTimeout(this._pointerHoverThrottleTimeout);
	}
	_initContainer() {
		const container = this._container = document.createElement("canvas");
		on(container, "pointermove", this._onPointerMove, this);
		on(container, "click dblclick pointerdown pointerup contextmenu", this._onClick, this);
		on(container, "pointerout", this._handlePointerOut, this);
		container["_maplair_disable_events"] = true;
		this._ctx = container.getContext("2d");
	}
	_destroyContainer() {
		cancelAnimationFrame(this._redrawRequest);
		this._redrawRequest = null;
		delete this._ctx;
		super._destroyContainer();
	}
	_resizeContainer() {
		const size = super._resizeContainer();
		const m = this._ctxScale = window.devicePixelRatio;
		this._container.width = m * size.x;
		this._container.height = m * size.y;
	}
	_updatePaths() {
		if (this._postponeUpdatePaths) return;
		this._redrawBounds = null;
		for (const layer of Object.values(this._layers)) layer._update();
		this._redraw();
	}
	_update() {
		if (this._map._animatingZoom && this._bounds) return;
		const b = this._bounds, s = this._ctxScale;
		this._ctx.setTransform(s, 0, 0, s, -b.min.x * s, -b.min.y * s);
		this.fire("update");
	}
	_reset() {
		super._reset();
		if (this._postponeUpdatePaths) {
			this._postponeUpdatePaths = false;
			this._updatePaths();
		}
	}
	_initPath(layer) {
		this._updateDashArray(layer);
		this._layers[stamp(layer)] = layer;
		const order = layer._order = {
			layer,
			prev: this._drawLast,
			next: null
		};
		if (this._drawLast) this._drawLast.next = order;
		this._drawLast = order;
		this._drawFirst ??= this._drawLast;
	}
	_addPath(layer) {
		this._requestRedraw(layer);
	}
	_removePath(layer) {
		const order = layer._order;
		const next = order.next;
		const prev = order.prev;
		if (next) next.prev = prev;
		else this._drawLast = prev;
		if (prev) prev.next = next;
		else this._drawFirst = next;
		delete layer._order;
		delete this._layers[stamp(layer)];
		this._requestRedraw(layer);
	}
	_updatePath(layer) {
		this._extendRedrawBounds(layer);
		layer._project();
		layer._update();
		this._requestRedraw(layer);
	}
	_updateStyle(layer) {
		this._updateDashArray(layer);
		this._requestRedraw(layer);
	}
	_updateDashArray(layer) {
		if (typeof layer.options.dashArray === "string") {
			const parts = layer.options.dashArray.split(DASH_SEPARATOR_RE);
			layer.options._dashArray = parts.map((n) => Number(n)).filter((n) => !isNaN(n));
		} else layer.options._dashArray = layer.options.dashArray;
	}
	_requestRedraw(layer) {
		if (!this._map) return;
		this._extendRedrawBounds(layer);
		this._redrawRequest ??= requestAnimationFrame(this._redraw.bind(this));
	}
	_extendRedrawBounds(layer) {
		if (layer._pxBounds) {
			const padding = (layer.options.weight ?? 0) + 1;
			this._redrawBounds ??= new Bounds();
			this._redrawBounds.extend(layer._pxBounds.min.subtract([padding, padding]));
			this._redrawBounds.extend(layer._pxBounds.max.add([padding, padding]));
		}
	}
	_redraw() {
		this._redrawRequest = null;
		if (this._redrawBounds) {
			this._redrawBounds.min._floor();
			this._redrawBounds.max._ceil();
		}
		this._clear();
		this._draw();
		this._redrawBounds = null;
	}
	_clear() {
		const bounds = this._redrawBounds;
		if (bounds) {
			const size = bounds.getSize();
			this._ctx.clearRect(bounds.min.x, bounds.min.y, size.x, size.y);
		} else {
			this._ctx.save();
			this._ctx.setTransform(1, 0, 0, 1, 0, 0);
			this._ctx.clearRect(0, 0, this._container.width, this._container.height);
			this._ctx.restore();
		}
	}
	_draw() {
		let layer;
		const bounds = this._redrawBounds;
		this._ctx.save();
		if (bounds) {
			const size = bounds.getSize();
			this._ctx.beginPath();
			this._ctx.rect(bounds.min.x, bounds.min.y, size.x, size.y);
			this._ctx.clip();
		}
		this._drawing = true;
		for (let order = this._drawFirst; order; order = order.next) {
			layer = order.layer;
			if (!bounds || layer._pxBounds && layer._pxBounds.intersects(bounds)) layer._updatePath();
		}
		this._drawing = false;
		this._ctx.restore();
	}
	_updatePoly(layer, closed) {
		if (!this._drawing) return;
		const parts = layer._parts, ctx = this._ctx;
		if (!parts.length) return;
		ctx.beginPath();
		parts.forEach((p0) => {
			p0.forEach((p, j) => {
				ctx[j ? "lineTo" : "moveTo"](p.x, p.y);
			});
			if (closed) ctx.closePath();
		});
		this._fillStroke(ctx, layer);
	}
	_updateCircle(layer) {
		if (!this._drawing || layer._empty()) return;
		const p = layer._point, ctx = this._ctx, r = Math.max(Math.round(layer._pxRadius), 1), s = (Math.max(Math.round(layer._pxRadiusY), 1) || r) / r;
		if (s !== 1) {
			ctx.save();
			ctx.scale(1, s);
		}
		ctx.beginPath();
		ctx.arc(p.x, p.y / s, r, 0, Math.PI * 2, false);
		if (s !== 1) ctx.restore();
		this._fillStroke(ctx, layer);
	}
	_fillStroke(ctx, layer) {
		const options = layer.options;
		if (options.fill) {
			ctx.globalAlpha = options.fillOpacity;
			ctx.fillStyle = options.fillColor ?? options.color;
			ctx.fill(options.fillRule || "evenodd");
		}
		if (options.stroke && options.weight !== 0) {
			ctx.lineDashOffset = Number(options.dashOffset ?? 0);
			ctx.setLineDash(options._dashArray ?? []);
			ctx.globalAlpha = options.opacity;
			ctx.lineWidth = options.weight;
			ctx.strokeStyle = options.color;
			ctx.lineCap = options.lineCap;
			ctx.lineJoin = options.lineJoin;
			ctx.stroke();
		}
	}
	_onClick(e) {
		const point = this._map.pointerEventToLayerPoint(e);
		let layer, clickedLayer;
		for (let order = this._drawFirst; order; order = order.next) {
			layer = order.layer;
			if (layer.options.interactive && layer._containsPoint(point)) {
				if (!(e.type === "click" || e.type === "preclick") || !this._map._draggableMoved(layer)) clickedLayer = layer;
			}
		}
		this._fireEvent(clickedLayer ? [clickedLayer] : false, e);
	}
	_onPointerMove(e) {
		if (!this._map || this._map.dragging.moving() || this._map._animatingZoom) return;
		const point = this._map.pointerEventToLayerPoint(e);
		this._handlePointerHover(e, point);
	}
	_handlePointerOut(e) {
		const layer = this._hoveredLayer;
		if (layer) {
			this._container.classList.remove("maplair-interactive");
			this._fireEvent([layer], e, "pointerout");
			this._hoveredLayer = null;
			this._pointerHoverThrottled = false;
		}
	}
	_handlePointerHover(e, point) {
		if (this._pointerHoverThrottled) return;
		let layer, candidateHoveredLayer;
		for (let order = this._drawFirst; order; order = order.next) {
			layer = order.layer;
			if (layer.options.interactive && layer._containsPoint(point)) candidateHoveredLayer = layer;
		}
		if (candidateHoveredLayer !== this._hoveredLayer) {
			this._handlePointerOut(e);
			if (candidateHoveredLayer) {
				this._container.classList.add("maplair-interactive");
				this._fireEvent([candidateHoveredLayer], e, "pointerover");
				this._hoveredLayer = candidateHoveredLayer;
			}
		}
		this._fireEvent(this._hoveredLayer ? [this._hoveredLayer] : false, e);
		this._pointerHoverThrottled = true;
		this._pointerHoverThrottleTimeout = setTimeout((() => {
			this._pointerHoverThrottled = false;
		}), 32);
	}
	_fireEvent(layers, e, type) {
		this._map._fireDOMEvent(e, type || e.type, layers);
	}
	_bringToFront(layer) {
		const order = layer._order;
		if (!order) return;
		const next = order.next;
		const prev = order.prev;
		if (next) next.prev = prev;
		else return;
		if (prev) prev.next = next;
		else if (next) this._drawFirst = next;
		order.prev = this._drawLast;
		this._drawLast.next = order;
		order.next = null;
		this._drawLast = order;
		this._requestRedraw(layer);
	}
	_bringToBack(layer) {
		const order = layer._order;
		if (!order) return;
		const next = order.next;
		const prev = order.prev;
		if (prev) prev.next = next;
		else return;
		if (next) next.prev = prev;
		else if (prev) this._drawLast = prev;
		order.prev = null;
		order.next = this._drawFirst;
		this._drawFirst.prev = order;
		this._drawFirst = order;
		this._requestRedraw(layer);
	}
};
//#endregion
//#region src/layer/vector/SVG.js
var SVG = class SVG extends Renderer {
	constructor(...args) {
		super(...args);
		this.callInitHooks(SVG);
	}
	_initContainer() {
		this._container = SVG.create("svg");
		this._container.setAttribute("pointer-events", "none");
		this._rootGroup = SVG.create("g");
		this._container.appendChild(this._rootGroup);
	}
	_destroyContainer() {
		super._destroyContainer();
		delete this._rootGroup;
		delete this._svgSize;
	}
	_resizeContainer() {
		const size = super._resizeContainer();
		if (!this._svgSize || !this._svgSize.equals(size)) {
			this._svgSize = size;
			this._container.setAttribute("width", size.x);
			this._container.setAttribute("height", size.y);
		}
		const b = this._bounds;
		if (b) this._container.setAttribute("viewBox", [
			b.min.x,
			b.min.y,
			size.x,
			size.y
		].join(" "));
	}
	_update() {
		if (this._map._animatingZoom && this._bounds) return;
		const b = this._bounds, size = b.getSize();
		this._container.setAttribute("viewBox", [
			b.min.x,
			b.min.y,
			size.x,
			size.y
		].join(" "));
		this.fire("update");
	}
	_initPath(layer) {
		const path = layer._path = SVG.create("path");
		if (layer.options.className) path.classList.add(...splitWords(layer.options.className));
		if (layer.options.interactive) path.classList.add("maplair-interactive");
		this._updateStyle(layer);
		this._layers[stamp(layer)] = layer;
	}
	_addPath(layer) {
		if (!this._rootGroup) this._initContainer();
		this._rootGroup.appendChild(layer._path);
		layer.addInteractiveTarget(layer._path);
	}
	_removePath(layer) {
		layer._path.remove();
		layer.removeInteractiveTarget(layer._path);
		delete this._layers[stamp(layer)];
	}
	_updatePath(layer) {
		layer._project();
		layer._update();
	}
	_updateStyle(layer) {
		const path = layer._path, options = layer.options;
		if (!path) return;
		if (options.stroke) {
			path.setAttribute("stroke", options.color);
			path.setAttribute("stroke-opacity", options.opacity);
			path.setAttribute("stroke-width", options.weight);
			path.setAttribute("stroke-linecap", options.lineCap);
			path.setAttribute("stroke-linejoin", options.lineJoin);
			if (options.dashArray) path.setAttribute("stroke-dasharray", options.dashArray);
			else path.removeAttribute("stroke-dasharray");
			if (options.dashOffset) path.setAttribute("stroke-dashoffset", options.dashOffset);
			else path.removeAttribute("stroke-dashoffset");
		} else path.setAttribute("stroke", "none");
		if (options.fill) {
			path.setAttribute("fill", options.fillColor || options.color);
			path.setAttribute("fill-opacity", options.fillOpacity);
			path.setAttribute("fill-rule", options.fillRule || "evenodd");
		} else path.setAttribute("fill", "none");
	}
	_updatePoly(layer, closed) {
		this._setPath(layer, SVG.pointsToPath(layer._parts, closed));
	}
	_updateCircle(layer) {
		const p = layer._point, r = Math.max(Math.round(layer._pxRadius), 1), arc = `a${r},${Math.max(Math.round(layer._pxRadiusY), 1) || r} 0 1,0 `;
		const d = layer._empty() ? "M0 0" : `M${p.x - r},${p.y}${arc}${r * 2},0 ${arc}${-r * 2},0 `;
		this._setPath(layer, d);
	}
	_setPath(layer, path) {
		layer._path.setAttribute("d", path);
	}
	_bringToFront(layer) {
		toFront(layer._path);
	}
	_bringToBack(layer) {
		toBack(layer._path);
	}
	static create(name) {
		return document.createElementNS("http://www.w3.org/2000/svg", name);
	}
	static pointsToPath(rings, closed) {
		return rings.flatMap((points) => [...points.map((p, j) => `${(j ? "L" : "M") + p.x} ${p.y}`), closed ? "z" : ""]).join("") || "M0 0";
	}
};
//#endregion
//#region src/layer/vector/Rectangle.js
var Rectangle = class Rectangle extends Polygon {
	constructor(latLngBounds, options) {
		super(Rectangle._boundsToLatLngs(latLngBounds), options);
		this.callInitHooks(Rectangle);
	}
	setBounds(latLngBounds) {
		return this.setLatLngs(Rectangle._boundsToLatLngs(latLngBounds));
	}
	static _boundsToLatLngs(latLngBounds) {
		latLngBounds = new LatLngBounds(latLngBounds);
		return [
			latLngBounds.getSouthWest(),
			latLngBounds.getNorthWest(),
			latLngBounds.getNorthEast(),
			latLngBounds.getSouthEast()
		];
	}
};
//#endregion
//#region src/layer/vector/Renderer.getRenderer.js
var Renderer_getRenderer_exports = /* @__PURE__ */ __exportAll({ register: () => register });
function register(MaplairMap) {
	MaplairMap.include({
		getRenderer(layer) {
			let renderer = layer.options.renderer ?? this._getPaneRenderer(layer.options.pane) ?? this.options.renderer ?? this._renderer;
			if (!renderer) renderer = this._renderer = this._createRenderer();
			if (!this.hasLayer(renderer)) this.addLayer(renderer);
			return renderer;
		},
		_getPaneRenderer(name) {
			if (name === "overlayPane" || name === void 0) return;
			let renderer = this._paneRenderers[name];
			if (renderer === void 0) {
				renderer = this._createRenderer({ pane: name });
				this._paneRenderers[name] = renderer;
			}
			return renderer;
		},
		_createRenderer(options) {
			return this.options.preferCanvas && new Canvas(options) || new SVG(options);
		}
	});
}
//#endregion
//#region src/map/handler/BoxZoomHandler.js
var BoxZoomHandler = class BoxZoomHandler extends Handler {
	constructor(map) {
		super(map);
		this._container = map._container;
		this._pane = map._panes.overlayPane;
		this._resetStateTimeout = 0;
		map.on("unload", this._destroy, this);
		this.callInitHooks(BoxZoomHandler);
	}
	addHooks() {
		on(this._container, "pointerdown", this._onPointerDown, this);
	}
	removeHooks() {
		off(this._container, "pointerdown", this._onPointerDown, this);
	}
	moved() {
		return this._moved;
	}
	_destroy() {
		this._pane.remove();
		delete this._pane;
	}
	_resetState() {
		this._resetStateTimeout = 0;
		this._moved = false;
	}
	_clearDeferredResetState() {
		if (this._resetStateTimeout !== 0) {
			clearTimeout(this._resetStateTimeout);
			this._resetStateTimeout = 0;
		}
	}
	_onPointerDown(e) {
		if (!e.shiftKey || e.button !== 0) return false;
		this._clearDeferredResetState();
		this._resetState();
		disableTextSelection();
		disableImageDrag();
		this._startPoint = this._map.pointerEventToContainerPoint(e);
		on(this._container, {
			contextmenu: stop,
			pointermove: this._onPointerMove,
			pointerup: this._onPointerUp,
			keydown: this._onKeyDown
		}, this);
		on(document, "keydown", this._onKeyDown, this);
	}
	_onPointerMove(e) {
		if (!this._moved) {
			this._moved = true;
			this._box = create("div", "maplair-zoom-box", this._container);
			this._container.classList.add("maplair-crosshair");
			this._map.fire("boxzoomstart");
		}
		this._point = this._map.pointerEventToContainerPoint(e);
		const bounds = new Bounds(this._point, this._startPoint), size = bounds.getSize();
		setPosition(this._box, bounds.min);
		this._box.style.width = `${size.x}px`;
		this._box.style.height = `${size.y}px`;
	}
	_finish() {
		if (this._moved) {
			this._box.remove();
			this._container.classList.remove("maplair-crosshair");
		}
		enableTextSelection();
		enableImageDrag();
		off(this._container, {
			contextmenu: stop,
			pointermove: this._onPointerMove,
			pointerup: this._onPointerUp
		}, this);
		off(document, "keydown", this._onKeyDown, this);
	}
	_onPointerUp(e) {
		if (e.button !== 0) return;
		this._finish();
		if (!this._moved) return;
		this._clearDeferredResetState();
		this._resetStateTimeout = setTimeout(this._resetState.bind(this), 0);
		const bounds = new LatLngBounds(this._map.containerPointToLatLng(this._startPoint), this._map.containerPointToLatLng(this._point));
		this._map.fitBounds(bounds).fire("boxzoomend", { boxZoomBounds: bounds });
	}
	_onKeyDown(e) {
		if (e.code === "Escape") {
			this._finish();
			this._clearDeferredResetState();
			this._resetState();
		}
	}
	static register(MaplairMap) {
		MaplairMap.mergeOptions({ boxZoom: true });
		MaplairMap.addInitHook("addHandler", "boxZoom", BoxZoomHandler);
	}
};
//#endregion
//#region src/map/handler/DoubleClickZoomHandler.js
var DoubleClickZoomHandler = class DoubleClickZoomHandler extends Handler {
	constructor(...args) {
		super(...args);
		this.callInitHooks(DoubleClickZoomHandler);
	}
	addHooks() {
		this._map.on("dblclick", this._onDoubleClick, this);
	}
	removeHooks() {
		this._map.off("dblclick", this._onDoubleClick, this);
	}
	_onDoubleClick(e) {
		const map = this._map, oldZoom = map.getZoom(), delta = map.options.zoomDelta, zoom = e.originalEvent.shiftKey ? oldZoom - delta : oldZoom + delta;
		if (map.options.doubleClickZoom === "center") map.setZoom(zoom);
		else map.setZoomAround(e.containerPoint, zoom);
	}
	static register(MaplairMap) {
		MaplairMap.mergeOptions({ doubleClickZoom: true });
		MaplairMap.addInitHook("addHandler", "doubleClickZoom", DoubleClickZoomHandler);
	}
};
//#endregion
//#region src/map/handler/DragHandler.js
var DragHandler = class DragHandler extends Handler {
	constructor(...args) {
		super(...args);
		this.callInitHooks(DragHandler);
	}
	addHooks() {
		if (!this._draggable) {
			const map = this._map;
			this._draggable = new Draggable(map._mapPane, map._container);
			this._draggable.on({
				dragstart: this._onDragStart,
				drag: this._onDrag,
				dragend: this._onDragEnd
			}, this);
			this._draggable.on("predrag", this._onPreDragLimit, this);
			if (map.options.worldCopyJump) {
				this._draggable.on("predrag", this._onPreDragWrap, this);
				map.on("zoomend", this._onZoomEnd, this);
				map.whenReady(this._onZoomEnd, this);
			}
		}
		this._map._container.classList.add("maplair-grab", "maplair-touch-drag");
		this._draggable.enable();
		this._positions = [];
		this._times = [];
	}
	removeHooks() {
		this._map._container.classList.remove("maplair-grab", "maplair-touch-drag");
		this._draggable.disable();
	}
	moved() {
		return this._draggable?._moved;
	}
	moving() {
		return this._draggable?._moving;
	}
	_onDragStart() {
		const map = this._map;
		map._stop();
		if (this._map.options.maxBounds && this._map.options.maxBoundsViscosity) {
			const bounds = new LatLngBounds(this._map.options.maxBounds);
			this._offsetLimit = new Bounds(this._map.latLngToContainerPoint(bounds.getNorthWest()).multiplyBy(-1), this._map.latLngToContainerPoint(bounds.getSouthEast()).multiplyBy(-1).add(this._map.getSize()));
			this._viscosity = Math.min(1, Math.max(0, this._map.options.maxBoundsViscosity));
		} else this._offsetLimit = null;
		map.fire("movestart").fire("dragstart");
		if (map.options.inertia) {
			this._positions = [];
			this._times = [];
		}
	}
	_onDrag(e) {
		if (this._map.options.inertia) {
			const time = this._lastTime = Date.now(), pos = this._lastPos = this._draggable._absPos || this._draggable._newPos;
			this._positions.push(pos);
			this._times.push(time);
			this._prunePositions(time);
		}
		this._map.fire("move", e).fire("drag", e);
	}
	_prunePositions(time) {
		while (this._positions.length > 1 && time - this._times[0] > 50) {
			this._positions.shift();
			this._times.shift();
		}
	}
	_onZoomEnd() {
		const pxCenter = this._map.getSize().divideBy(2), pxWorldCenter = this._map.latLngToLayerPoint([0, 0]);
		this._initialWorldOffset = pxWorldCenter.subtract(pxCenter).x;
		this._worldWidth = this._map.getPixelWorldBounds().getSize().x;
	}
	_viscousLimit(value, threshold) {
		return value - (value - threshold) * this._viscosity;
	}
	_onPreDragLimit() {
		if (!this._viscosity || !this._offsetLimit) return;
		const offset = this._draggable._newPos.subtract(this._draggable._startPos);
		const limit = this._offsetLimit;
		if (offset.x < limit.min.x) offset.x = this._viscousLimit(offset.x, limit.min.x);
		if (offset.y < limit.min.y) offset.y = this._viscousLimit(offset.y, limit.min.y);
		if (offset.x > limit.max.x) offset.x = this._viscousLimit(offset.x, limit.max.x);
		if (offset.y > limit.max.y) offset.y = this._viscousLimit(offset.y, limit.max.y);
		this._draggable._newPos = this._draggable._startPos.add(offset);
	}
	_onPreDragWrap() {
		const worldWidth = this._worldWidth, halfWidth = Math.round(worldWidth / 2), dx = this._initialWorldOffset, x = this._draggable._newPos.x, newX1 = (x - halfWidth + dx) % worldWidth + halfWidth - dx, newX2 = (x + halfWidth + dx) % worldWidth - halfWidth - dx, newX = Math.abs(newX1 + dx) < Math.abs(newX2 + dx) ? newX1 : newX2;
		this._draggable._absPos = new Point(this._draggable._newPos);
		this._draggable._newPos.x = newX;
	}
	_onDragEnd(e) {
		const map = this._map, options = map.options, noInertia = !options.inertia || e.noInertia || this._times.length < 2;
		map.fire("dragend", e);
		if (noInertia) map.fire("moveend");
		else {
			this._prunePositions(Date.now());
			const direction = this._lastPos.subtract(this._positions[0]), duration = (this._lastTime - this._times[0]) / 1e3, ease = options.easeLinearity, speedVector = direction.multiplyBy(ease / duration), speed = speedVector.distanceTo([0, 0]), limitedSpeed = Math.min(options.inertiaMaxSpeed, speed), limitedSpeedVector = speedVector.multiplyBy(limitedSpeed / speed), decelerationDuration = limitedSpeed / (options.inertiaDeceleration * ease);
			let offset = limitedSpeedVector.multiplyBy(-decelerationDuration / 2).round();
			if (!offset.x && !offset.y) map.fire("moveend");
			else {
				offset = map._limitOffset(offset, map.options.maxBounds);
				requestAnimationFrame(() => {
					map.panBy(offset, {
						duration: decelerationDuration,
						easeLinearity: ease,
						noMoveStart: true,
						animate: true
					});
				});
			}
		}
	}
	static register(MaplairMap) {
		MaplairMap.mergeOptions({
			dragging: true,
			inertia: true,
			inertiaDeceleration: 3400,
			inertiaMaxSpeed: Infinity,
			easeLinearity: .2,
			worldCopyJump: false,
			maxBoundsViscosity: 0
		});
		MaplairMap.addInitHook("addHandler", "dragging", DragHandler);
	}
};
//#endregion
//#region src/map/handler/KeyboardHandler.js
var KeyboardHandler = class KeyboardHandler extends Handler {
	static keyCodes = {
		left: ["ArrowLeft"],
		right: ["ArrowRight"],
		down: ["ArrowDown"],
		up: ["ArrowUp"],
		zoomIn: [
			"Equal",
			"NumpadAdd",
			"BracketRight"
		],
		zoomOut: [
			"Minus",
			"NumpadSubtract",
			"Digit6",
			"Slash"
		]
	};
	constructor(map) {
		super(map);
		this._setPanDelta(map.options.keyboardPanDelta);
		this._setZoomDelta(map.options.zoomDelta);
		this.callInitHooks(KeyboardHandler);
	}
	addHooks() {
		const container = this._map._container;
		if (container.tabIndex <= 0) container.tabIndex = "0";
		container.ariaKeyShortcuts = Object.values(KeyboardHandler.keyCodes).flat().join(" ");
		on(container, {
			focus: this._onFocus,
			blur: this._onBlur,
			pointerdown: this._onPointerDown
		}, this);
		this._map.on({
			focus: this._addHooks,
			blur: this._removeHooks
		}, this);
	}
	removeHooks() {
		this._removeHooks();
		off(this._map._container, {
			focus: this._onFocus,
			blur: this._onBlur,
			pointerdown: this._onPointerDown
		}, this);
		this._map.off({
			focus: this._addHooks,
			blur: this._removeHooks
		}, this);
	}
	_onPointerDown() {
		if (this._focused) return;
		const body = document.body, docEl = document.documentElement, top = body.scrollTop || docEl.scrollTop, left = body.scrollLeft || docEl.scrollLeft;
		this._map._container.focus();
		window.scrollTo(left, top);
	}
	_onFocus() {
		this._focused = true;
		this._map.fire("focus");
	}
	_onBlur() {
		this._focused = false;
		this._map.fire("blur");
	}
	_setPanDelta(panDelta) {
		const keys = this._panKeys = {}, codes = KeyboardHandler.keyCodes;
		for (const code of codes.left) keys[code] = [-1 * panDelta, 0];
		for (const code of codes.right) keys[code] = [panDelta, 0];
		for (const code of codes.down) keys[code] = [0, panDelta];
		for (const code of codes.up) keys[code] = [0, -1 * panDelta];
	}
	_setZoomDelta(zoomDelta) {
		const keys = this._zoomKeys = {}, codes = KeyboardHandler.keyCodes;
		for (const code of codes.zoomIn) keys[code] = zoomDelta;
		for (const code of codes.zoomOut) keys[code] = -zoomDelta;
	}
	_addHooks() {
		on(document, "keydown", this._onKeyDown, this);
	}
	_removeHooks() {
		off(document, "keydown", this._onKeyDown, this);
	}
	_onKeyDown(e) {
		if (e.altKey || e.ctrlKey || e.metaKey) return;
		const key = e.code, map = this._map;
		let offset;
		if (key in this._panKeys) {
			if (!map._panAnim || !map._panAnim._inProgress) {
				offset = this._panKeys[key];
				if (e.shiftKey) offset = new Point(offset).multiplyBy(3);
				if (map.options.maxBounds) offset = map._limitOffset(new Point(offset), map.options.maxBounds);
				if (map.options.worldCopyJump) {
					const newLatLng = map.wrapLatLng(map.unproject(map.project(map.getCenter()).add(offset)));
					map.panTo(newLatLng);
				} else map.panBy(offset);
			}
		} else if (key in this._zoomKeys) map.setZoom(map.getZoom() + (e.shiftKey ? 3 : 1) * this._zoomKeys[key]);
		else if (key === "Escape" && map._popup && map._popup.options.closeOnEscapeKey) map.closePopup();
		else return;
		stop(e);
	}
	static register(MaplairMap) {
		MaplairMap.mergeOptions({
			keyboard: true,
			keyboardPanDelta: 80
		});
		MaplairMap.addInitHook("addHandler", "keyboard", KeyboardHandler);
	}
};
//#endregion
//#region src/map/handler/PinchZoomHandler.js
var PinchZoomHandler = class PinchZoomHandler extends Handler {
	constructor(...args) {
		super(...args);
		this.callInitHooks(PinchZoomHandler);
	}
	addHooks() {
		this._map._container.classList.add("maplair-touch-zoom");
		on(this._map._container, "pointerdown", this._onPointerStart, this);
	}
	removeHooks() {
		this._map._container.classList.remove("maplair-touch-zoom");
		off(this._map._container, "pointerdown", this._onPointerStart, this);
		off(this._map._container, "pointermove", this._onPointerMove, this);
		off(this._map._container, "pointerup pointercancel", this._onPointerEnd, this);
	}
	_onPointerStart(e) {
		const map = this._map;
		const pointers = getPointers();
		if (pointers.length !== 2 || map._animatingZoom || this._zooming) return;
		const p1 = map.pointerEventToContainerPoint(pointers[0]), p2 = map.pointerEventToContainerPoint(pointers[1]);
		this._centerPoint = map.getSize()._divideBy(2);
		this._startLatLng = map.containerPointToLatLng(this._centerPoint);
		if (map.options.pinchZoom !== "center") this._pinchStartLatLng = map.containerPointToLatLng(p1.add(p2)._divideBy(2));
		this._startDist = p1.distanceTo(p2);
		this._startZoom = map.getZoom();
		this._moved = false;
		this._zooming = true;
		map._stop();
		on(this._map._container, "pointermove", this._onPointerMove, this);
		on(this._map._container, "pointerup pointercancel", this._onPointerEnd, this);
		e.preventDefault();
	}
	_onPointerMove(e) {
		const pointers = getPointers();
		if (pointers.length !== 2 || !this._zooming) return;
		const map = this._map, p1 = map.pointerEventToContainerPoint(pointers[0]), p2 = map.pointerEventToContainerPoint(pointers[1]), scale = p1.distanceTo(p2) / this._startDist;
		this._zoom = map.getScaleZoom(scale, this._startZoom);
		if (!map.options.bounceAtZoomLimits && (this._zoom < map.getMinZoom() && scale < 1 || this._zoom > map.getMaxZoom() && scale > 1)) this._zoom = map._limitZoom(this._zoom);
		if (map.options.pinchZoom === "center") {
			this._center = this._startLatLng;
			if (scale === 1) return;
		} else {
			const delta = p1._add(p2)._divideBy(2)._subtract(this._centerPoint);
			if (scale === 1 && delta.x === 0 && delta.y === 0) return;
			this._center = map.unproject(map.project(this._pinchStartLatLng, this._zoom).subtract(delta), this._zoom);
		}
		if (!this._moved) {
			map._moveStart(true, false);
			this._moved = true;
		}
		cancelAnimationFrame(this._animRequest);
		const moveFn = map._move.bind(map, this._center, this._zoom, {
			pinch: true,
			round: false
		}, void 0);
		this._animRequest = requestAnimationFrame(moveFn.bind(this));
		e.preventDefault();
	}
	_onPointerEnd() {
		off(this._map._container, "pointermove", this._onPointerMove, this);
		off(this._map._container, "pointerup pointercancel", this._onPointerEnd, this);
		if (!this._moved || !this._zooming) {
			this._zooming = false;
			return;
		}
		this._zooming = false;
		cancelAnimationFrame(this._animRequest);
		if (this._map.options.zoomAnimation) this._map._animateZoom(this._center, this._map._limitZoom(this._zoom), true, this._map.options.zoomSnap);
		else this._map._resetView(this._center, this._map._limitZoom(this._zoom));
	}
	static register(MaplairMap) {
		MaplairMap.mergeOptions({
			pinchZoom: true,
			bounceAtZoomLimits: true
		});
		MaplairMap.addInitHook("addHandler", "pinchZoom", PinchZoomHandler);
		MaplairMap.addInitHook(function() {
			this.touchZoom = this.pinchZoom;
			if (this.options.touchZoom !== void 0) {
				console.warn("Map: touchZoom option is deprecated and will be removed in future versions. Use pinchZoom instead.");
				this.options.pinchZoom = this.options.touchZoom;
				delete this.options.touchZoom;
			}
			if (this.options.pinchZoom) this.pinchZoom.enable();
			else this.pinchZoom.disable();
		});
	}
};
//#endregion
//#region src/map/handler/ScrollWheelZoomHandler.js
var ScrollWheelZoomHandler = class ScrollWheelZoomHandler extends Handler {
	constructor(...args) {
		super(...args);
		this.callInitHooks(ScrollWheelZoomHandler);
	}
	addHooks() {
		on(this._map._container, "wheel", this._onWheelScroll, this);
		this._delta = 0;
	}
	removeHooks() {
		off(this._map._container, "wheel", this._onWheelScroll, this);
		clearTimeout(this._timer);
	}
	_onWheelScroll(e) {
		const delta = getWheelDelta(e);
		const debounce = this._map.options.wheelDebounceTime;
		this._delta += delta;
		this._lastMousePos = this._map.pointerEventToContainerPoint(e);
		if (!this._startTime) this._startTime = Date.now();
		const left = Math.max(debounce - (Date.now() - this._startTime), 0);
		clearTimeout(this._timer);
		this._timer = setTimeout(this._performZoom.bind(this), left);
		stop(e);
	}
	_performZoom() {
		const map = this._map, zoom = map.getZoom(), snap = this._map.options.zoomSnap ?? 0;
		map._stop();
		const d2 = this._delta / (this._map.options.wheelPxPerZoomLevel * 4), d3 = 4 * Math.log(2 / (1 + Math.exp(-Math.abs(d2)))) / Math.LN2, d4 = snap ? Math.ceil(d3 / snap) * snap : d3, delta = map._limitZoom(zoom + (this._delta > 0 ? d4 : -d4)) - zoom;
		this._delta = 0;
		this._startTime = null;
		if (!delta) return;
		if (map.options.scrollWheelZoom === "center") map.setZoom(zoom + delta);
		else map.setZoomAround(this._lastMousePos, zoom + delta);
	}
	static register(MaplairMap) {
		MaplairMap.mergeOptions({
			scrollWheelZoom: true,
			wheelDebounceTime: 40,
			wheelPxPerZoomLevel: 60
		});
		MaplairMap.addInitHook("addHandler", "scrollWheelZoom", ScrollWheelZoomHandler);
	}
};
//#endregion
//#region src/map/handler/TapHoldHandler.js
const tapHoldDelay = 600;
var TapHoldHandler = class TapHoldHandler extends Handler {
	constructor(...args) {
		super(...args);
		this.callInitHooks(TapHoldHandler);
	}
	addHooks() {
		on(this._map._container, "pointerdown", this._onDown, this);
	}
	removeHooks() {
		off(this._map._container, "pointerdown", this._onDown, this);
		this._cancel();
		this._cancelClickPrevent();
	}
	_onDown(e) {
		clearTimeout(this._holdTimeout);
		if (getPointers().length !== 1 || e.pointerType === "mouse") return;
		const el = this._map._container;
		this._startPos = this._newPos = new Point(e.clientX, e.clientY);
		this._holdTimeout = setTimeout((() => {
			this._cancel();
			if (!this._isTapValid()) return;
			on(el, "pointerup", preventDefault);
			on(el, "pointerup pointercancel", this._cancelClickPrevent, this);
			this._simulateEvent("contextmenu", e);
		}), tapHoldDelay);
		on(el, "pointerup pointercancel contextmenu", this._cancel, this);
		on(el, "pointermove", this._onMove, this);
	}
	_cancelClickPrevent() {
		const el = this._map._container;
		off(el, "pointerup", preventDefault);
		off(el, "pointerup pointercancel", this._cancelClickPrevent, this);
	}
	_cancel() {
		clearTimeout(this._holdTimeout);
		const el = this._map._container;
		off(el, "pointerup pointercancel contextmenu", this._cancel, this);
		off(el, "pointermove", this._onMove, this);
	}
	_onMove(e) {
		this._newPos = new Point(e.clientX, e.clientY);
	}
	_isTapValid() {
		return this._newPos.distanceTo(this._startPos) <= this._map.options.tapTolerance;
	}
	_simulateEvent(type, e) {
		const simulatedEvent = new MouseEvent(type, {
			bubbles: true,
			cancelable: true,
			view: window,
			screenX: e.screenX,
			screenY: e.screenY,
			clientX: e.clientX,
			clientY: e.clientY
		});
		simulatedEvent._simulated = true;
		e.target.dispatchEvent(simulatedEvent);
	}
	static register(MaplairMap) {
		MaplairMap.mergeOptions({
			tapHold: Browser_default.safari && Browser_default.mobile,
			tapTolerance: 15
		});
		MaplairMap.addInitHook("addHandler", "tapHold", TapHoldHandler);
	}
};
//#endregion
//#region src/map/Map.js
var MaplairMap = class MaplairMap extends Evented {
	static {
		this.setDefaultOptions({
			crs: EPSG3857,
			center: void 0,
			zoom: void 0,
			minZoom: void 0,
			maxZoom: void 0,
			layers: [],
			maxBounds: void 0,
			renderer: void 0,
			zoomAnimation: !Browser_default.reducedMotion,
			zoomAnimationThreshold: 4,
			fadeAnimation: !Browser_default.reducedMotion,
			markerZoomAnimation: true,
			markerCulling: false,
			transform3DLimit: 8388608,
			zoomSnap: 1,
			zoomDelta: 1,
			trackResize: true
		});
	}
	constructor(id, options) {
		super();
		options = setOptions(this, options);
		this._handlers = [];
		this._layers = {};
		this._zoomBoundLayers = {};
		this._sizeChanged = true;
		this._initContainer(id);
		this._initLayout();
		this._initEvents();
		if (options.maxBounds) this.setMaxBounds(options.maxBounds);
		if (options.zoom !== void 0) this._zoom = this._limitZoom(options.zoom);
		if (options.center && options.zoom !== void 0) this.setView(new LatLng(options.center), options.zoom, { reset: true });
		this.callInitHooks(MaplairMap);
		this._zoomAnimated = this.options.zoomAnimation;
		if (this._zoomAnimated) this._createAnimProxy();
		this._addLayers(this.options.layers);
	}
	setView(center, zoom, options) {
		zoom = zoom === void 0 ? this._zoom : this._limitZoom(zoom);
		center = this._limitCenter(new LatLng(center), zoom, this.options.maxBounds);
		options ??= {};
		this._stop();
		if (this._loaded && !options.reset && options !== true) {
			if (options.animate !== void 0) {
				options.zoom = {
					animate: options.animate,
					...options.zoom
				};
				options.pan = {
					animate: options.animate,
					duration: options.duration,
					...options.pan
				};
			}
			if (this._zoom !== zoom ? this._tryAnimatedZoom && this._tryAnimatedZoom(center, zoom, options.zoom) : this._tryAnimatedPan(center, options.pan)) {
				clearTimeout(this._sizeTimer);
				return this;
			}
		}
		this._resetView(center, zoom, options.pan?.noMoveStart);
		return this;
	}
	setZoom(zoom, options) {
		if (!this._loaded) {
			this._zoom = zoom;
			return this;
		}
		return this.setView(this.getCenter(), zoom, { zoom: options });
	}
	zoomIn(delta, options) {
		delta ??= this.options.zoomDelta;
		return this.setZoom(this._zoom + delta, options);
	}
	zoomOut(delta, options) {
		delta ??= this.options.zoomDelta;
		return this.setZoom(this._zoom - delta, options);
	}
	setZoomAround(latlng, zoom, options) {
		const scale = this.getZoomScale(zoom), viewHalf = this.getSize().divideBy(2), centerOffset = (latlng instanceof Point ? latlng : this.latLngToContainerPoint(latlng)).subtract(viewHalf).multiplyBy(1 - 1 / scale), newCenter = this.containerPointToLatLng(viewHalf.add(centerOffset));
		return this.setView(newCenter, zoom, { zoom: options });
	}
	_getBoundsCenterZoom(bounds, options) {
		options ??= {};
		bounds = bounds.getBounds ? bounds.getBounds() : new LatLngBounds(bounds);
		const paddingTL = new Point(options.paddingTopLeft || options.padding || [0, 0]), paddingBR = new Point(options.paddingBottomRight || options.padding || [0, 0]);
		let zoom = this.getBoundsZoom(bounds, false, paddingTL.add(paddingBR));
		zoom = typeof options.maxZoom === "number" ? Math.min(options.maxZoom, zoom) : zoom;
		if (zoom === Infinity) return {
			center: bounds.getCenter(),
			zoom
		};
		const paddingOffset = paddingBR.subtract(paddingTL).divideBy(2), swPoint = this.project(bounds.getSouthWest(), zoom), nePoint = this.project(bounds.getNorthEast(), zoom);
		return {
			center: this.unproject(swPoint.add(nePoint).divideBy(2).add(paddingOffset), zoom),
			zoom
		};
	}
	fitBounds(bounds, options) {
		bounds = new LatLngBounds(bounds);
		if (!bounds.isValid()) throw new Error("Bounds are not valid.");
		const target = this._getBoundsCenterZoom(bounds, options);
		return this.setView(target.center, target.zoom, options);
	}
	fitWorld(options) {
		return this.fitBounds([[-90, -180], [90, 180]], options);
	}
	panTo(center, options) {
		return this.setView(center, this._zoom, { pan: options });
	}
	panBy(offset, options) {
		offset = new Point(offset).round();
		options ??= {};
		if (!offset.x && !offset.y) return this.fire("moveend");
		if (options.animate !== true && !this.getSize().contains(offset)) {
			this._resetView(this.unproject(this.project(this.getCenter()).add(offset)), this.getZoom());
			return this;
		}
		if (!this._panAnim) {
			this._panAnim = new PosAnimation();
			this._panAnim.on({
				"step": this._onPanTransitionStep,
				"end": this._onPanTransitionEnd
			}, this);
		}
		if (!options.noMoveStart) this.fire("movestart");
		if (!Browser_default.reducedMotion && options.animate !== false) {
			this._mapPane.classList.add("maplair-pan-anim");
			const newPos = this._getMapPanePos().subtract(offset).round();
			this._panAnim.run(this._mapPane, newPos, options.duration || .25, options.easeLinearity);
		} else {
			this._rawPanBy(offset);
			this.fire("move").fire("moveend");
		}
		return this;
	}
	flyTo(targetCenter, targetZoom, options) {
		options ??= {};
		if (Browser_default.reducedMotion || options.animate === false) return this.setView(targetCenter, targetZoom, options);
		this._stop();
		const from = this.project(this.getCenter()), to = this.project(targetCenter), size = this.getSize(), startZoom = this._zoom;
		targetCenter = new LatLng(targetCenter);
		targetZoom = targetZoom === void 0 ? startZoom : this._limitZoom(targetZoom);
		const w0 = Math.max(size.x, size.y), w1 = w0 * this.getZoomScale(startZoom, targetZoom), u1 = to.distanceTo(from) || 1, rho = 1.42, rho2 = rho * rho;
		function r(i) {
			const s1 = i ? -1 : 1, s2 = i ? w1 : w0, b = (w1 * w1 - w0 * w0 + s1 * rho2 * rho2 * u1 * u1) / (2 * s2 * rho2 * u1), sq = Math.sqrt(b * b + 1) - b;
			return sq < 15e-9 ? -18 : Math.log(sq);
		}
		function sinh(n) {
			return (Math.exp(n) - Math.exp(-n)) / 2;
		}
		function cosh(n) {
			return (Math.exp(n) + Math.exp(-n)) / 2;
		}
		function tanh(n) {
			return sinh(n) / cosh(n);
		}
		const r0 = r(0);
		function w(s) {
			return w0 * (cosh(r0) / cosh(r0 + rho * s));
		}
		function u(s) {
			return w0 * (cosh(r0) * tanh(r0 + rho * s) - sinh(r0)) / rho2;
		}
		function easeOut(t) {
			return 1 - (1 - t) ** 1.5;
		}
		const start = Date.now(), S = (r(1) - r0) / rho, duration = options.duration ? 1e3 * options.duration : 1e3 * S * .8;
		const frame = () => {
			const t = (Date.now() - start) / duration, s = easeOut(t) * S;
			if (t <= 1) {
				this._flyToFrame = requestAnimationFrame(frame);
				this._move(this.unproject(from.add(to.subtract(from).multiplyBy(u(s) / u1)), startZoom), this.getScaleZoom(w0 / w(s), startZoom), { flyTo: true });
			} else this._move(targetCenter, targetZoom)._moveEnd(true);
		};
		this._moveStart(true, options.noMoveStart);
		frame(this);
		return this;
	}
	flyToBounds(bounds, options) {
		const target = this._getBoundsCenterZoom(bounds, options);
		return this.flyTo(target.center, target.zoom, options);
	}
	setMaxBounds(bounds) {
		bounds = new LatLngBounds(bounds);
		if (this.listens("moveend", this._panInsideMaxBounds)) this.off("moveend", this._panInsideMaxBounds);
		if (!bounds.isValid()) {
			this.options.maxBounds = null;
			return this;
		}
		this.options.maxBounds = bounds;
		if (this._loaded) this._panInsideMaxBounds();
		return this.on("moveend", this._panInsideMaxBounds);
	}
	setMinZoom(zoom) {
		const oldZoom = this.options.minZoom;
		this.options.minZoom = zoom;
		if (this._loaded && oldZoom !== zoom) {
			this.fire("zoomlevelschange");
			if (this.getZoom() < this.options.minZoom) return this.setZoom(zoom);
		}
		return this;
	}
	setMaxZoom(zoom) {
		const oldZoom = this.options.maxZoom;
		this.options.maxZoom = zoom;
		if (this._loaded && oldZoom !== zoom) {
			this.fire("zoomlevelschange");
			if (this.getZoom() > this.options.maxZoom) return this.setZoom(zoom);
		}
		return this;
	}
	panInsideBounds(bounds, options) {
		this._enforcingBounds = true;
		const center = this.getCenter(), newCenter = this._limitCenter(center, this._zoom, new LatLngBounds(bounds));
		if (!center.equals(newCenter)) this.panTo(newCenter, options);
		this._enforcingBounds = false;
		return this;
	}
	panInside(latlng, options) {
		options ??= {};
		const paddingTL = new Point(options.paddingTopLeft || options.padding || [0, 0]), paddingBR = new Point(options.paddingBottomRight || options.padding || [0, 0]), pixelCenter = this.project(this.getCenter()), pixelPoint = this.project(latlng), pixelBounds = this.getPixelBounds(), paddedBounds = new Bounds([pixelBounds.min.add(paddingTL), pixelBounds.max.subtract(paddingBR)]), paddedSize = paddedBounds.getSize();
		if (!paddedBounds.contains(pixelPoint)) {
			this._enforcingBounds = true;
			const centerOffset = pixelPoint.subtract(paddedBounds.getCenter());
			const offset = paddedBounds.extend(pixelPoint).getSize().subtract(paddedSize);
			pixelCenter.x += centerOffset.x < 0 ? -offset.x : offset.x;
			pixelCenter.y += centerOffset.y < 0 ? -offset.y : offset.y;
			this.panTo(this.unproject(pixelCenter), options);
			this._enforcingBounds = false;
		}
		return this;
	}
	invalidateSize(options) {
		if (!this._loaded) return this;
		options = {
			animate: false,
			pan: true,
			...options === true ? { animate: true } : options
		};
		const oldSize = this.getSize();
		this._sizeChanged = true;
		this._lastCenter = null;
		const newSize = this.getSize(), oldCenter = oldSize.divideBy(2).round(), newCenter = newSize.divideBy(2).round(), offset = oldCenter.subtract(newCenter);
		if (!offset.x && !offset.y) return this;
		if (options.animate && options.pan) this.panBy(offset);
		else {
			if (options.pan) this._rawPanBy(offset);
			this.fire("move");
			if (options.debounceMoveend) {
				clearTimeout(this._sizeTimer);
				this._sizeTimer = setTimeout(this.fire.bind(this, "moveend"), 200);
			} else this.fire("moveend");
		}
		return this.fire("resize", {
			oldSize,
			newSize
		});
	}
	stop() {
		this.setZoom(this._limitZoom(this._zoom));
		if (!this.options.zoomSnap) this.fire("viewreset");
		return this._stop();
	}
	locate(options) {
		options = this._locateOptions = {
			timeout: 1e4,
			watch: false,
			...options
		};
		if (!("geolocation" in navigator)) {
			this._handleGeolocationError({
				code: 0,
				message: "Geolocation not supported."
			});
			return this;
		}
		const onResponse = this._handleGeolocationResponse.bind(this), onError = this._handleGeolocationError.bind(this);
		if (options.watch) {
			if (this._locationWatchId !== void 0) navigator.geolocation.clearWatch(this._locationWatchId);
			this._locationWatchId = navigator.geolocation.watchPosition(onResponse, onError, options);
		} else navigator.geolocation.getCurrentPosition(onResponse, onError, options);
		return this;
	}
	stopLocate() {
		navigator.geolocation?.clearWatch?.(this._locationWatchId);
		if (this._locateOptions) this._locateOptions.setView = false;
		return this;
	}
	_handleGeolocationError(error) {
		if (!this._container._maplair_id) return;
		const c = error.code, message = error.message || (c === 1 ? "permission denied" : c === 2 ? "position unavailable" : "timeout");
		if (this._locateOptions.setView && !this._loaded) this.fitWorld();
		this.fire("locationerror", {
			code: c,
			message: `Geolocation error: ${message}.`
		});
	}
	_handleGeolocationResponse(pos) {
		if (!this._container._maplair_id) return;
		const lat = pos.coords.latitude, lng = pos.coords.longitude, latlng = new LatLng(lat, lng), bounds = latlng.toBounds(pos.coords.accuracy * 2), options = this._locateOptions;
		if (options.setView) {
			const zoom = this.getBoundsZoom(bounds);
			this.setView(latlng, options.maxZoom ? Math.min(zoom, options.maxZoom) : zoom);
		}
		const data = {
			latlng,
			bounds,
			timestamp: pos.timestamp
		};
		for (const i in pos.coords) if (typeof pos.coords[i] === "number") data[i] = pos.coords[i];
		this.fire("locationfound", data);
	}
	addHandler(name, HandlerClass) {
		if (!HandlerClass) return this;
		const handler = this[name] = new HandlerClass(this);
		this._handlers.push(handler);
		if (this.options[name]) handler.enable();
		return this;
	}
	remove() {
		this._initEvents(true);
		if (this.options.maxBounds) this.off("moveend", this._panInsideMaxBounds);
		if (this._containerId !== this._container._maplair_id) throw new Error("Map container is being reused by another instance");
		delete this._container._maplair_id;
		delete this._containerId;
		if (this._locationWatchId !== void 0) this.stopLocate();
		this._stop();
		disablePointerDetection(this._container);
		this._mapPane.remove();
		if (this._clearControlPos) this._clearControlPos();
		if (this._resizeRequest) {
			cancelAnimationFrame(this._resizeRequest);
			this._resizeRequest = null;
		}
		this._clearHandlers();
		clearTimeout(this._transitionEndTimer);
		clearTimeout(this._sizeTimer);
		if (this._loaded) this.fire("unload");
		this._destroyAnimProxy();
		for (const layer of Object.values(this._layers)) layer.remove();
		for (const pane of Object.values(this._panes)) pane.remove();
		this._layers = {};
		this._panes = {};
		delete this._mapPane;
		delete this._renderer;
		return this;
	}
	createPane(name, container) {
		const pane = create("div", `maplair-pane${name ? ` maplair-${name.replace("Pane", "")}-pane` : ""}`, container || this._mapPane);
		if (name) this._panes[name] = pane;
		return pane;
	}
	getCenter() {
		this._checkIfLoaded();
		if (this._lastCenter && !this._moved()) return new LatLng(this._lastCenter);
		return this.layerPointToLatLng(this._getCenterLayerPoint());
	}
	getZoom() {
		return this._zoom;
	}
	getBounds() {
		const bounds = this.getPixelBounds();
		return new LatLngBounds(this.unproject(bounds.getBottomLeft()), this.unproject(bounds.getTopRight()));
	}
	getMinZoom() {
		return this.options.minZoom ?? this._layersMinZoom ?? 0;
	}
	getMaxZoom() {
		return this.options.maxZoom ?? this._layersMaxZoom ?? Infinity;
	}
	getBoundsZoom(bounds, inside, padding) {
		bounds = new LatLngBounds(bounds);
		padding = new Point(padding ?? [0, 0]);
		let zoom = this.getZoom() ?? 0;
		const min = this.getMinZoom(), max = this.getMaxZoom(), nw = bounds.getNorthWest(), se = bounds.getSouthEast(), size = this.getSize().subtract(padding), boundsSize = new Bounds(this.project(se, zoom), this.project(nw, zoom)).getSize(), snap = this.options.zoomSnap, scalex = size.x / boundsSize.x, scaley = size.y / boundsSize.y, scale = inside ? Math.max(scalex, scaley) : Math.min(scalex, scaley);
		zoom = this.getScaleZoom(scale, zoom);
		if (snap) {
			zoom = Math.round(zoom / (snap / 100)) * (snap / 100);
			zoom = inside ? Math.ceil(zoom / snap) * snap : Math.floor(zoom / snap) * snap;
		}
		return Math.max(min, Math.min(max, zoom));
	}
	getSize() {
		if (!this._size || this._sizeChanged) {
			this._size = new Point(this._container.clientWidth || 0, this._container.clientHeight || 0);
			this._sizeChanged = false;
		}
		return new Point(this._size);
	}
	getPixelBounds(center, zoom) {
		const topLeftPoint = this._getTopLeftPoint(center, zoom);
		return new Bounds(topLeftPoint, topLeftPoint.add(this.getSize()));
	}
	getPixelOrigin() {
		this._checkIfLoaded();
		return this._pixelOrigin;
	}
	getPixelWorldBounds(zoom) {
		return this.options.crs.getProjectedBounds(zoom ?? this.getZoom());
	}
	getPane(pane) {
		return typeof pane === "string" ? this._panes[pane] : pane;
	}
	getPanes() {
		return this._panes;
	}
	getContainer() {
		return this._container;
	}
	getZoomScale(toZoom, fromZoom) {
		const crs = this.options.crs;
		fromZoom ??= this._zoom;
		return crs.scale(toZoom) / crs.scale(fromZoom);
	}
	getScaleZoom(scale, fromZoom) {
		const crs = this.options.crs;
		fromZoom ??= this._zoom;
		const zoom = crs.zoom(scale * crs.scale(fromZoom));
		return isNaN(zoom) ? Infinity : zoom;
	}
	project(latlng, zoom) {
		zoom ??= this._zoom;
		return this.options.crs.latLngToPoint(new LatLng(latlng), zoom);
	}
	unproject(point, zoom) {
		zoom ??= this._zoom;
		return this.options.crs.pointToLatLng(new Point(point), zoom);
	}
	layerPointToLatLng(point) {
		const projectedPoint = new Point(point).add(this.getPixelOrigin());
		return this.unproject(projectedPoint);
	}
	latLngToLayerPoint(latlng) {
		return this.project(new LatLng(latlng))._round()._subtract(this.getPixelOrigin());
	}
	wrapLatLng(latlng) {
		return this.options.crs.wrapLatLng(new LatLng(latlng));
	}
	wrapLatLngBounds(bounds) {
		return this.options.crs.wrapLatLngBounds(new LatLngBounds(bounds));
	}
	distance(latlng1, latlng2) {
		return this.options.crs.distance(new LatLng(latlng1), new LatLng(latlng2));
	}
	containerPointToLayerPoint(point) {
		return new Point(point).subtract(this._getMapPanePos());
	}
	layerPointToContainerPoint(point) {
		return new Point(point).add(this._getMapPanePos());
	}
	containerPointToLatLng(point) {
		const layerPoint = this.containerPointToLayerPoint(new Point(point));
		return this.layerPointToLatLng(layerPoint);
	}
	latLngToContainerPoint(latlng) {
		return this.layerPointToContainerPoint(this.latLngToLayerPoint(new LatLng(latlng)));
	}
	pointerEventToContainerPoint(e) {
		return getPointerPosition(e, this._container);
	}
	pointerEventToLayerPoint(e) {
		return this.containerPointToLayerPoint(this.pointerEventToContainerPoint(e));
	}
	pointerEventToLatLng(e) {
		return this.layerPointToLatLng(this.pointerEventToLayerPoint(e));
	}
	_initContainer(id) {
		const container = this._container = get(id);
		if (!container) throw new Error("Map container not found.");
		else if (container._maplair_id) throw new Error("Map container is already initialized.");
		enablePointerDetection(container);
		on(container, "scroll", this._onScroll, this);
		this._containerId = stamp(container);
	}
	_initLayout() {
		const container = this._container;
		this._fadeAnimated = this.options.fadeAnimation;
		const classes = ["maplair-container", "maplair-touch"];
		if (Browser_default.retina) classes.push("maplair-retina");
		if (Browser_default.safari) classes.push("maplair-safari");
		if (this._fadeAnimated) classes.push("maplair-fade-anim");
		container.classList.add(...classes);
		const { position } = getComputedStyle(container);
		if (position !== "absolute" && position !== "relative" && position !== "fixed" && position !== "sticky") container.style.position = "relative";
		this._initPanes();
		if (this._initControlPos) this._initControlPos();
	}
	_initPanes() {
		const panes = this._panes = {};
		this._paneRenderers = {};
		this._mapPane = this.createPane("mapPane", this._container);
		setPosition(this._mapPane, new Point(0, 0));
		this.createPane("tilePane");
		this.createPane("overlayPane");
		this.createPane("shadowPane");
		this.createPane("markerPane");
		this.createPane("tooltipPane");
		this.createPane("popupPane");
		if (!this.options.markerZoomAnimation) {
			panes.markerPane.classList.add("maplair-zoom-hide");
			panes.shadowPane.classList.add("maplair-zoom-hide");
		}
	}
	_resetView(center, zoom, noMoveStart) {
		setPosition(this._mapPane, new Point(0, 0));
		const loading = !this._loaded;
		this._loaded = true;
		zoom = this._limitZoom(zoom);
		this.fire("viewprereset");
		const zoomChanged = this._zoom !== zoom;
		this._moveStart(zoomChanged, noMoveStart)._move(center, zoom)._moveEnd(zoomChanged);
		this.fire("viewreset");
		if (loading) this.fire("load");
	}
	_moveStart(zoomChanged, noMoveStart) {
		if (zoomChanged) this.fire("zoomstart");
		if (!noMoveStart) this.fire("movestart");
		return this;
	}
	_move(center, zoom, data, suppressEvent) {
		if (zoom === void 0) zoom = this._zoom;
		const zoomChanged = this._zoom !== zoom;
		this._zoom = zoom;
		this._lastCenter = center;
		this._pixelOrigin = this._getNewPixelOrigin(center);
		if (!suppressEvent) {
			if (zoomChanged || data?.pinch) this.fire("zoom", data);
			this.fire("move", data);
		} else if (data?.pinch) this.fire("zoom", data);
		return this;
	}
	_moveEnd(zoomChanged) {
		if (zoomChanged) this.fire("zoomend");
		return this.fire("moveend");
	}
	_stop() {
		cancelAnimationFrame(this._flyToFrame);
		cancelAnimationFrame(this._zoomAnimFrame);
		this._panAnim?.stop();
		return this;
	}
	_rawPanBy(offset) {
		setPosition(this._mapPane, this._getMapPanePos().subtract(offset));
	}
	_getZoomSpan() {
		return this.getMaxZoom() - this.getMinZoom();
	}
	_panInsideMaxBounds() {
		if (!this._enforcingBounds) this.panInsideBounds(this.options.maxBounds);
	}
	_checkIfLoaded() {
		if (!this._loaded) throw new Error("Set map center and zoom first.");
	}
	_initEvents(remove) {
		this._targets = {};
		this._targets[stamp(this._container)] = this;
		(remove ? off : on)(this._container, "click dblclick pointerdown pointerup pointerover pointerout pointermove contextmenu keypress keydown keyup", this._handleDOMEvent, this);
		if (this.options.trackResize) {
			if (!remove) {
				if (!this._resizeObserver) this._resizeObserver = new ResizeObserver(this._onResize.bind(this));
				this._resizeObserver.observe(this._container);
			} else this._resizeObserver.disconnect();
		}
		if (this.options.transform3DLimit) (remove ? this.off : this.on).call(this, "moveend", this._onMoveEnd);
	}
	_onResize() {
		cancelAnimationFrame(this._resizeRequest);
		this._resizeRequest = requestAnimationFrame(() => {
			this.invalidateSize({ debounceMoveend: true });
		});
	}
	_onScroll() {
		this._container.scrollTop = 0;
		this._container.scrollLeft = 0;
	}
	_onMoveEnd() {
		const pos = this._getMapPanePos();
		if (Math.max(Math.abs(pos.x), Math.abs(pos.y)) >= this.options.transform3DLimit) this._resetView(this.getCenter(), this.getZoom());
	}
	_findEventTargets(e, type) {
		let targets = [], target, src = e.target || e.srcElement, dragging = false;
		const isHover = type === "pointerout" || type === "pointerover";
		while (src) {
			target = this._targets[stamp(src)];
			if (target && (type === "click" || type === "preclick") && this._draggableMoved(target)) {
				dragging = true;
				break;
			}
			if (target && target.listens(type, true)) {
				if (isHover && !isExternalTarget(src, e)) break;
				targets.push(target);
				if (isHover) break;
			}
			if (src === this._container) break;
			src = src.parentNode;
		}
		if (!targets.length && !dragging && !isHover && this.listens(type, true)) targets = [this];
		return targets;
	}
	_isClickDisabled(el) {
		while (el && el !== this._container) {
			if (el["_maplair_disable_click"] || !el.parentNode) return true;
			el = el.parentNode;
		}
	}
	_handleDOMEvent(e) {
		const el = e.target ?? e.srcElement;
		if (!this._loaded || el["_maplair_disable_events"] || e.type === "click" && this._isClickDisabled(el)) return;
		const type = e.type;
		if (type === "pointerdown") preventOutline(el);
		this._fireDOMEvent(e, type);
	}
	static _pointerEvents = [
		"click",
		"dblclick",
		"pointerover",
		"pointerout",
		"contextmenu"
	];
	_fireDOMEvent(e, type, canvasTargets) {
		if (type === "click") this._fireDOMEvent(e, "preclick", canvasTargets);
		let targets = this._findEventTargets(e, type);
		if (canvasTargets) targets = [...canvasTargets.filter((t) => t.listens(type, true)), ...targets];
		if (!targets.length) return;
		if (type === "contextmenu") e.preventDefault();
		const target = targets[0];
		const data = { originalEvent: e };
		if (e.type !== "keypress" && e.type !== "keydown" && e.type !== "keyup") {
			const isMarker = target.getLatLng && (!target._pxRadius || target._pxRadius <= 10);
			data.containerPoint = isMarker ? this.latLngToContainerPoint(target.getLatLng()) : this.pointerEventToContainerPoint(e);
			data.layerPoint = this.containerPointToLayerPoint(data.containerPoint);
			data.latlng = isMarker ? target.getLatLng() : this.layerPointToLatLng(data.layerPoint);
		}
		for (const t of targets) {
			t.fire(type, data, true);
			if (data.originalEvent._stopped || t.options.bubblingPointerEvents === false && MaplairMap._pointerEvents.includes(type)) return;
		}
	}
	_draggableMoved(obj) {
		obj = obj.dragging?.enabled() ? obj : this;
		return obj.dragging?.moved() || this.boxZoom?.moved();
	}
	_clearHandlers() {
		for (const handler of this._handlers) handler.disable();
	}
	whenReady(callback, context) {
		if (this._loaded) callback.call(context || this, { target: this });
		else this.on("load", callback, context);
		return this;
	}
	_getMapPanePos() {
		return getPosition(this._mapPane);
	}
	_moved() {
		const pos = this._getMapPanePos();
		return pos && !pos.equals([0, 0]);
	}
	_getTopLeftPoint(center, zoom) {
		return (center && zoom !== void 0 ? this._getNewPixelOrigin(center, zoom) : this.getPixelOrigin()).subtract(this._getMapPanePos());
	}
	_getNewPixelOrigin(center, zoom) {
		const viewHalf = this.getSize()._divideBy(2);
		return this.project(center, zoom)._subtract(viewHalf)._add(this._getMapPanePos())._round();
	}
	_latLngToNewLayerPoint(latlng, zoom, center) {
		const topLeft = this._getNewPixelOrigin(center, zoom);
		return this.project(latlng, zoom)._subtract(topLeft);
	}
	_latLngBoundsToNewLayerBounds(latLngBounds, zoom, center) {
		const topLeft = this._getNewPixelOrigin(center, zoom);
		return new Bounds([
			this.project(latLngBounds.getSouthWest(), zoom)._subtract(topLeft),
			this.project(latLngBounds.getNorthWest(), zoom)._subtract(topLeft),
			this.project(latLngBounds.getSouthEast(), zoom)._subtract(topLeft),
			this.project(latLngBounds.getNorthEast(), zoom)._subtract(topLeft)
		]);
	}
	_getCenterLayerPoint() {
		return this.containerPointToLayerPoint(this.getSize()._divideBy(2));
	}
	_getCenterOffset(latlng) {
		return this.latLngToLayerPoint(latlng).subtract(this._getCenterLayerPoint());
	}
	_limitCenter(center, zoom, bounds) {
		if (!bounds) return center;
		const centerPoint = this.project(center, zoom), viewHalf = this.getSize().divideBy(2), viewBounds = new Bounds(centerPoint.subtract(viewHalf), centerPoint.add(viewHalf)), offset = this._getBoundsOffset(viewBounds, bounds, zoom);
		if (Math.abs(offset.x) <= 1 && Math.abs(offset.y) <= 1) return center;
		return this.unproject(centerPoint.add(offset), zoom);
	}
	_limitOffset(offset, bounds) {
		if (!bounds) return offset;
		const viewBounds = this.getPixelBounds(), newBounds = new Bounds(viewBounds.min.add(offset), viewBounds.max.add(offset));
		return offset.add(this._getBoundsOffset(newBounds, bounds));
	}
	_getBoundsOffset(pxBounds, maxBounds, zoom) {
		const projectedMaxBounds = new Bounds(this.project(maxBounds.getNorthEast(), zoom), this.project(maxBounds.getSouthWest(), zoom)), minOffset = projectedMaxBounds.min.subtract(pxBounds.min), maxOffset = projectedMaxBounds.max.subtract(pxBounds.max);
		return new Point(this._rebound(minOffset.x, -maxOffset.x), this._rebound(minOffset.y, -maxOffset.y));
	}
	_rebound(left, right) {
		return left + right > 0 ? Math.round(left - right) / 2 : Math.max(0, Math.ceil(left)) - Math.max(0, Math.floor(right));
	}
	_limitZoom(zoom) {
		const min = this.getMinZoom(), max = this.getMaxZoom(), snap = this.options.zoomSnap;
		if (snap) zoom = Math.round(zoom / snap) * snap;
		return Math.max(min, Math.min(max, zoom));
	}
	_onPanTransitionStep() {
		this.fire("move");
	}
	_onPanTransitionEnd() {
		this._mapPane.classList.remove("maplair-pan-anim");
		this.fire("moveend");
	}
	_tryAnimatedPan(center, options) {
		const offset = this._getCenterOffset(center)._trunc();
		if (options?.animate !== true && !this.getSize().contains(offset)) return false;
		this.panBy(offset, options);
		return true;
	}
	_createAnimProxy() {
		this._proxy = create("div", "maplair-proxy maplair-zoom-animated");
		this._panes.mapPane.appendChild(this._proxy);
		this.on("zoomanim", this._animateProxyZoom, this);
		this.on("load moveend", this._animMoveEnd, this);
		on(this._proxy, "transitionend", this._catchTransitionEnd, this);
	}
	_animateProxyZoom(e) {
		const transform = this._proxy.style.transform;
		setTransform(this._proxy, this.project(e.center, e.zoom), this.getZoomScale(e.zoom, 1));
		if (transform === this._proxy.style.transform && this._animatingZoom) this._onZoomTransitionEnd();
	}
	_animMoveEnd() {
		const c = this.getCenter();
		const z = this.getZoom();
		setTransform(this._proxy, this.project(c, z), this.getZoomScale(z, 1));
	}
	_destroyAnimProxy() {
		if (this._proxy) {
			off(this._proxy, "transitionend", this._catchTransitionEnd, this);
			this._proxy.remove();
			this.off("zoomanim", this._animateProxyZoom, this);
			this.off("load moveend", this._animMoveEnd, this);
			delete this._proxy;
		}
	}
	_catchTransitionEnd(e) {
		if (this._animatingZoom && e.propertyName.includes("transform")) this._onZoomTransitionEnd();
	}
	_nothingToAnimate() {
		return !this._container.getElementsByClassName("maplair-zoom-animated").length;
	}
	_tryAnimatedZoom(center, zoom, options) {
		if (this._animatingZoom) return true;
		options ??= {};
		if (!this._zoomAnimated || options.animate === false || this._nothingToAnimate() || Math.abs(zoom - this._zoom) > this.options.zoomAnimationThreshold) return false;
		const scale = this.getZoomScale(zoom), offset = this._getCenterOffset(center)._divideBy(1 - 1 / scale);
		if (options.animate !== true && !this.getSize().contains(offset)) return false;
		this._zoomAnimFrame = requestAnimationFrame(() => {
			this._zoomAnimFrame = null;
			this._moveStart(true, options.noMoveStart ?? false)._animateZoom(center, zoom, true);
		});
		return true;
	}
	_animateZoom(center, zoom, startAnim, noUpdate) {
		if (!this._mapPane) return;
		if (startAnim) {
			this._animatingZoom = true;
			this._animateToCenter = center;
			this._animateToZoom = zoom;
			this._mapPane.classList.add("maplair-zoom-anim");
		}
		this.fire("zoomanim", {
			center,
			zoom,
			noUpdate
		});
		if (!this._tempFireZoomEvent) this._tempFireZoomEvent = this._zoom !== this._animateToZoom;
		this._move(this._animateToCenter, this._animateToZoom, void 0, true);
		this._transitionEndTimer = setTimeout(this._onZoomTransitionEnd.bind(this), 250);
	}
	_onZoomTransitionEnd() {
		if (!this._animatingZoom) return;
		this._mapPane?.classList.remove("maplair-zoom-anim");
		this._animatingZoom = false;
		this._move(this._animateToCenter, this._animateToZoom, void 0, true);
		if (this._tempFireZoomEvent) this.fire("zoom");
		delete this._tempFireZoomEvent;
		this.fire("move");
		this._moveEnd(true);
	}
};
for (const feature of [
	AttributionControl,
	Control,
	DivOverlay,
	Layer,
	BoxZoomHandler,
	DoubleClickZoomHandler,
	DragHandler,
	KeyboardHandler,
	PinchZoomHandler,
	ScrollWheelZoomHandler,
	TapHoldHandler,
	Popup,
	Tooltip,
	Renderer_getRenderer_exports,
	ZoomControl
]) feature.register(MaplairMap);
const Map$1 = MaplairMap;
//#endregion
//#region src/Maplair.js
const version = version$1;
//#endregion
export { AttributionControl, BlanketOverlay, Bounds, BoxZoomHandler, Browser_default as Browser, CRS, Canvas, Circle, CircleMarker, Class, Control, DefaultIcon, DivIcon, DivOverlay, DomEvent_exports as DomEvent, DomUtil_exports as DomUtil, DoubleClickZoomHandler, DragHandler, Draggable, EPSG3395, EPSG3857, EPSG4326, EPSG900913, EarthCRS, Evented, FeatureGroup, GeoJSON, GridLayer, Handler, I18n, Icon, ImageOverlay, KeyboardHandler, LatLng, LatLngBounds, Layer, LayerGroup, LayersControl, LineUtil_exports as LineUtil, Map$1 as Map, MaplairMap, Marker, Path, PinchZoomHandler, Point, PolyUtil_exports as PolyUtil, Polygon, Polyline, Popup, PosAnimation, projection_exports as Projection, Rectangle, Renderer, SVG, SVGOverlay, ScaleControl, ScrollWheelZoomHandler, SimpleCRS, TapHoldHandler, TileLayer, Tooltip, Transformation, Util_exports as Util, VideoOverlay, WMSTileLayer, ZoomControl, version };

//# sourceMappingURL=maplair-src.js.map