mahal_map 1.6.21 → 1.6.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +176 -0
- package/dist/index.d.mts +13 -5
- package/dist/index.d.ts +13 -5
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +5 -5
- package/dist/index.mjs.map +1 -1
- package/dist/mahal_map.sdk.js +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/core/CameraController.ts","../src/config/constants.ts","../src/services/authKey.ts","../src/markers/defaultMarkerSvg.ts","../src/markers/MahalMapDefaultMarker.ts","../src/markers/marker.adapter.ts","../src/core/MahalMap.ts","../src/services/index.ts","../src/services/httpClient.ts","../src/services/routing/routing.api.ts","../src/utils/index.ts","../src/utils/coordinates.ts","../src/utils/debounce.ts","../src/utils/polyline/geojsonPolyline.ts","../src/utils/polyline/geometryPolyline.ts","../src/utils/trimValue.ts","../src/services/routing/routing.service.ts","../src/services/search/search.api.ts","../src/services/search/search.service.ts","../src/measure/index.ts","../src/measure/geo.ts","../src/measure/svgSanitizer.ts","../src/measure/badge.ts","../src/measure/MeasureTool.ts"],"sourcesContent":["// Lib\r\nimport { MahalMap } from \"@core\";\r\nimport { Search, SearchByLocation, Router } from \"@services\";\r\nimport { MahalMapDefaultMarker } from \"@markers\";\r\nimport { MeasureTool } from \"@measure\";\r\n\r\n// utils\r\nimport * as keyUtils from \"@services\";\r\nimport * as utils from \"@utils\";\r\nimport * as measureUtils from \"@measure\";\r\n\r\nexport * from \"@sdk-types\";\r\nexport type {\r\n MeasureMode,\r\n MeasurePoint,\r\n MeasureShape,\r\n MeasureStyleOptions,\r\n MeasureIcons,\r\n MeasureLabels,\r\n MeasureToolOptions,\r\n MeasureState,\r\n} from \"@measure\";\r\n\r\nexport {\r\n MahalMap,\r\n Search,\r\n SearchByLocation,\r\n Router,\r\n keyUtils,\r\n MahalMapDefaultMarker,\r\n MeasureTool,\r\n measureUtils,\r\n utils,\r\n};\r\n","import type { Map, FlyToOptions } from \"maplibre-gl\";\r\n\r\nexport class CameraController {\r\n constructor(private map: Map) {}\r\n\r\n setZoom(zoom: number, smooth = true) {\r\n if (smooth) {\r\n this.map.easeTo({ zoom });\r\n } else {\r\n this.map.setZoom(zoom);\r\n }\r\n }\r\n\r\n setBearing(bearing: number, smooth = true) {\r\n smooth ? this.map.easeTo({ bearing }) : this.map.setBearing(bearing);\r\n }\r\n\r\n setPitch(pitch: number, smooth = true) {\r\n smooth ? this.map.easeTo({ pitch }) : this.map.setPitch(pitch);\r\n }\r\n\r\n toggle3D(is3D: boolean) {\r\n this.map.easeTo({\r\n pitch: is3D ? 60 : 0,\r\n bearing: is3D ? this.map.getBearing() : 0,\r\n duration: 800,\r\n });\r\n }\r\n\r\n resetNorth() {\r\n this.map.easeTo({\r\n bearing: 0,\r\n pitch: 0,\r\n duration: 600,\r\n });\r\n }\r\n\r\n flyTo(options: FlyToOptions) {\r\n this.map.flyTo({\r\n speed: 1.2,\r\n curve: 1.42,\r\n essential: true,\r\n ...options,\r\n });\r\n }\r\n\r\n getPitch() {\r\n return this.map.getPitch();\r\n }\r\n}\r\n","const BASE_URL = \"https://platform.mahal.tj/api/\";\r\nconst LATLNGREGEX =\r\n /^([-+]?(?:[1-8]?\\d(?:\\.\\d+)?|90(?:\\.0+)?)),\\s*([-+]?(?:180(?:\\.0+)?|(?:(?:1[0-7]\\d)|(?:[1-9]?\\d))(?:\\.\\d+)?))$/;\r\nconst LNGLATREGEX =\r\n /^([-+]?(?:180(?:\\.0+)?|(?:(?:1[0-7]\\d)|(?:[1-9]?\\d))(?:\\.\\d+)?)),\\s*([-+]?(?:[1-8]?\\d(?:\\.\\d+)?|90(?:\\.0+)?))$/;\r\n\r\nconst REGEX =\r\n /^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?),\\s*[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$/;\r\n\r\nconst DARK = \"https://mtile.gram.tj/custom-styles/dark-style.json\";\r\nconst LIGHT = \"https://mtile.gram.tj/custom-styles/mapstyle.json\";\r\nconst VECTOR =\r\n \"https://mtile.gram.tj/custom-styles/style_maptiler_basic_hn.json\";\r\n\r\nconst STYLE_LANG_PARAM = \"ru\";\r\n\r\nconst GRAM_BASE = \"https://navi.gram.tj\";\r\nconst GRAM_PRESETS = { light: \"road-urban-lab-v2\", dark: \"standard-night\" };\r\n\r\nfunction buildGramStyleUrl(base: string, preset: string) {\r\n return `${base}/maps/${preset}.json`;\r\n}\r\n\r\nfunction appendQueryParam(styleUrl: string, name: string, value: string) {\r\n const separator = styleUrl.includes(\"?\") ? \"&\" : \"?\";\r\n return `${styleUrl}${separator}${name}=${encodeURIComponent(value)}`;\r\n}\r\n\r\nfunction buildStyleUrl(styleUrl: string, lang?: string, token?: string) {\r\n let finalStyleUrl = styleUrl;\r\n\r\n if (token) {\r\n finalStyleUrl = appendQueryParam(finalStyleUrl, \"token\", token);\r\n }\r\n\r\n if (lang === STYLE_LANG_PARAM) {\r\n finalStyleUrl = appendQueryParam(finalStyleUrl, \"lang\", STYLE_LANG_PARAM);\r\n }\r\n\r\n return finalStyleUrl;\r\n}\r\n\r\nexport {\r\n BASE_URL,\r\n LATLNGREGEX,\r\n LNGLATREGEX,\r\n REGEX,\r\n DARK,\r\n LIGHT,\r\n VECTOR,\r\n buildStyleUrl,\r\n GRAM_BASE,\r\n GRAM_PRESETS,\r\n buildGramStyleUrl,\r\n};\r\n","let apiKey: string = \"\";\r\n\r\nfunction saveKey(param: string) {\r\n if (param === \"\") return;\r\n apiKey = param;\r\n}\r\n\r\nfunction clearKey() {\r\n apiKey = \"\";\r\n}\r\n\r\nconst getApiKey = () => apiKey;\r\n\r\nexport { saveKey, clearKey, getApiKey };\r\n","type DefaultMarkerInnerIconOptions = {\r\n innerSvg?: string;\r\n innerUrl?: string;\r\n};\r\n\r\nconst SVG_ROOT_PATTERN = /<svg[\\s>]/i;\r\nconst SVG_MARKUP_PATTERN =\r\n /<(svg|path|g|circle|rect|polygon|line|polyline|ellipse|use)\\b/i;\r\n\r\nconst updateSvgAttribute = (\r\n svg: string,\r\n attribute: string,\r\n value: string,\r\n): string => {\r\n const attributePattern = new RegExp(`\\\\s${attribute}=\"[^\"]*\"`, \"i\");\r\n\r\n if (attributePattern.test(svg)) {\r\n return svg.replace(attributePattern, ` ${attribute}=\"${value}\"`);\r\n }\r\n\r\n return svg.replace(/<svg\\b/i, `<svg ${attribute}=\"${value}\"`);\r\n};\r\n\r\nconst escapeSvgAttribute = (value: string): string =>\r\n value.replace(/&/g, \"&\").replace(/\"/g, \""\");\r\n\r\nconst createImageTag = (url: string): string =>\r\n `<image href=\"${escapeSvgAttribute(url)}\" x=\"14\" y=\"12\" width=\"22\" height=\"22\" style=\"filter: brightness(0) invert(1);\" />`;\r\n\r\nconst normalizeInnerSvg = (svg: string): string => {\r\n const trimmedSvg = svg.trim();\r\n\r\n if (SVG_ROOT_PATTERN.test(trimmedSvg)) {\r\n let normalizedSvg = updateSvgAttribute(trimmedSvg, \"x\", \"14\");\r\n normalizedSvg = updateSvgAttribute(normalizedSvg, \"y\", \"12\");\r\n normalizedSvg = updateSvgAttribute(normalizedSvg, \"width\", \"22\");\r\n normalizedSvg = updateSvgAttribute(normalizedSvg, \"height\", \"22\");\r\n\r\n if (!/\\spreserveAspectRatio=\"/i.test(normalizedSvg)) {\r\n normalizedSvg = normalizedSvg.replace(\r\n /<svg\\b/i,\r\n `<svg preserveAspectRatio=\"xMidYMid meet\"`,\r\n );\r\n }\r\n\r\n return normalizedSvg;\r\n }\r\n\r\n return `<g transform=\"translate(14 12)\">${trimmedSvg}</g>`;\r\n};\r\n\r\nconst resolveInnerIcon = ({\r\n innerSvg,\r\n innerUrl,\r\n}: DefaultMarkerInnerIconOptions): string => {\r\n const trimmedInnerSvg = innerSvg?.trim();\r\n const trimmedInnerUrl = innerUrl?.trim();\r\n\r\n if (trimmedInnerSvg) {\r\n if (SVG_MARKUP_PATTERN.test(trimmedInnerSvg)) {\r\n return normalizeInnerSvg(trimmedInnerSvg);\r\n }\r\n\r\n return createImageTag(trimmedInnerSvg);\r\n }\r\n\r\n if (trimmedInnerUrl) {\r\n return createImageTag(trimmedInnerUrl);\r\n }\r\n\r\n return \"\";\r\n};\r\n\r\nconst createDefaultMarkerSvg = (\r\n color: string,\r\n innerIconOptions: DefaultMarkerInnerIconOptions = {},\r\n) => `<svg\r\n width=\"50\"\r\n height=\"62\"\r\n viewBox=\"0 0 50 62\"\r\n fill=\"none\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n >\r\n <g filter=\"url(#filter0_d_367_31358)\">\r\n <path\r\n fill-rule=\"evenodd\"\r\n clip-rule=\"evenodd\"\r\n d=\"M25 2C36.598 2 46 11.402 46 23C46 33.1603 38.7844 41.6353 29.198 43.5803L25.6524 48.6575C25.5788 48.7633 25.4812 48.8497 25.3676 48.9093C25.254 48.9689 25.128 49 25 49C24.872 49 24.746 48.9689 24.6324 48.9093C24.5188 48.8497 24.4212 48.7633 24.3476 48.6575L20.802 43.5803C11.2156 41.6353 4 33.1603 4 23C4 11.402 13.402 2 25 2Z\"\r\n fill=\"${color ? color : \"#278960\"}\"\r\n />\r\n </g>\r\n <path\r\n d=\"M25 51C27.7614 51 30 53.2386 30 56C30 58.7614 27.7614 61 25 61C22.2386 61 20 58.7614 20 56C20 53.2386 22.2386 51 25 51Z\"\r\n fill=\"${color ? color : \"#278960\"}\"\r\n stroke=\"white\"\r\n stroke-width=\"2\"\r\n />\r\n <g clip-path=\"url(#clip0_367_31358)\">\r\n ${resolveInnerIcon(innerIconOptions)}\r\n </g>\r\n <defs>\r\n <filter\r\n id=\"filter0_d_367_31358\"\r\n x=\"0\"\r\n y=\"0\"\r\n width=\"50\"\r\n height=\"55\"\r\n filterUnits=\"userSpaceOnUse\"\r\n color-interpolation-filters=\"sRGB\"\r\n >\r\n <feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\" />\r\n <feColorMatrix\r\n in=\"SourceAlpha\"\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\r\n result=\"hardAlpha\"\r\n />\r\n <feOffset dy=\"2\" />\r\n <feGaussianBlur stdDeviation=\"2\" />\r\n <feComposite in2=\"hardAlpha\" operator=\"out\" />\r\n <feColorMatrix\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0.250234 0 0 0 0 0.660089 0 0 0 0 0.488619 0 0 0 0.24 0\"\r\n />\r\n <feBlend\r\n mode=\"normal\"\r\n in2=\"BackgroundImageFix\"\r\n result=\"effect1_dropShadow_367_31358\"\r\n />\r\n <feBlend\r\n mode=\"normal\"\r\n in=\"SourceGraphic\"\r\n in2=\"effect1_dropShadow_367_31358\"\r\n result=\"shape\"\r\n />\r\n </filter>\r\n <clipPath id=\"clip0_367_31358\">\r\n <rect\r\n width=\"22\"\r\n height=\"22\"\r\n fill=\"white\"\r\n transform=\"translate(14 12)\"\r\n />\r\n </clipPath>\r\n </defs>\r\n </svg>`;\r\n\r\nexport { createDefaultMarkerSvg };\r\n","import { createDefaultMarkerSvg } from \"./defaultMarkerSvg\";\r\nimport type { MahalMapDefaultMarkerProps } from \"@sdk-types\";\r\n\r\nclass MahalMapDefaultMarker {\r\n private element: HTMLElement;\r\n\r\n constructor(private props: MahalMapDefaultMarkerProps) {\r\n this.element = this.createElement();\r\n }\r\n\r\n private createElement(): HTMLElement {\r\n const el = document.createElement(\"div\");\r\n el.style.cursor = \"pointer\";\r\n\r\n const svg = this.props.svg\r\n ? this.applyColorToCustomSvg(this.props.svg)\r\n : createDefaultMarkerSvg(\r\n this.props.color ?? \"#278960\",\r\n {\r\n innerSvg: this.props.innerSvg,\r\n innerUrl: this.props.innerUrl,\r\n },\r\n );\r\n\r\n el.innerHTML = svg;\r\n\r\n if (this.props.draggable) {\r\n el.draggable = true;\r\n }\r\n\r\n return el;\r\n }\r\n\r\n private applyColorToCustomSvg(svg: string): string {\r\n if (!this.props.color) return svg;\r\n return svg.replace(/fill=\"[^\"]*\"/g, `fill=\"${this.props.color}\"`);\r\n }\r\n\r\n getElement() {\r\n return this.element;\r\n }\r\n\r\n getCoordinates() {\r\n return this.props.coordinates;\r\n }\r\n\r\n isDraggable() {\r\n return !!this.props.draggable;\r\n }\r\n\r\n getAnchor() {\r\n return this.props.anchor || \"center\";\r\n }\r\n}\r\n\r\nexport { MahalMapDefaultMarker };\r\n","import type { Map, Marker } from \"maplibre-gl\";\r\nimport type { IMapMarker } from \"@sdk-types\";\r\n\r\ntype MapLibreMarkerFactory = {\r\n Marker: new (...args: ConstructorParameters<typeof Marker>) => Marker;\r\n};\r\n\r\nexport function addMarker(\r\n maplibregl: MapLibreMarkerFactory,\r\n map: Map,\r\n marker: IMapMarker,\r\n) {\r\n const mapMarker = new maplibregl.Marker({\r\n element: marker.getElement(),\r\n draggable: marker.isDraggable?.() ?? false,\r\n anchor: marker.getAnchor?.() ?? \"center\",\r\n })\r\n .setLngLat(marker.getCoordinates())\r\n .addTo(map);\r\n\r\n return mapMarker;\r\n}\r\n","import type { Map as MapType, Marker } from \"maplibre-gl\";\r\nimport {\r\n DARK,\r\n LIGHT,\r\n VECTOR,\r\n buildStyleUrl,\r\n GRAM_BASE,\r\n GRAM_PRESETS,\r\n buildGramStyleUrl,\r\n} from \"@config\";\r\nimport { CameraController } from \"./CameraController\";\r\n\r\nimport type {\r\n IMahalMapOptions,\r\n IMapMarker,\r\n MapEngine,\r\n MapLanguage,\r\n Maps3DCtor,\r\n IMaps3DLayer,\r\n Theme,\r\n} from \"@sdk-types\";\r\nimport { getApiKey } from \"@services/authKey\";\r\n\r\n// Adapter\r\nimport { addMarker } from \"@markers\";\r\n\r\nconst defaultStyles = { dark: DARK, light: LIGHT };\r\nconst logoColors = { dark: \"#ffffff\", light: \"#19191a\" };\r\n\r\ntype MapLibreApi = {\r\n Map: new (...args: ConstructorParameters<typeof MapType>) => MapType;\r\n Marker: new (...args: ConstructorParameters<typeof Marker>) => Marker;\r\n};\r\n\r\nexport class MahalMap {\r\n private static instances = new Map<string, MahalMap>();\r\n private static defaultLanguage: MapLanguage = \"tj\";\r\n\r\n private isReady = false;\r\n private readyCallbacks: Array<(map: MapType) => void> = [];\r\n\r\n private map!: MapType;\r\n private maplibre!: MapLibreApi;\r\n private camera!: CameraController;\r\n private logoHost?: HTMLDivElement;\r\n private logoShadow?: ShadowRoot;\r\n private logoObserver?: MutationObserver;\r\n\r\n private options!: IMahalMapOptions;\r\n private language: MapLanguage = \"tj\";\r\n private instanceKey = \"\";\r\n\r\n private engine: MapEngine = \"legacy\";\r\n private gramBase: string = GRAM_BASE;\r\n private gramPreset: string = GRAM_PRESETS.light;\r\n private presetIsExplicit = false;\r\n private maps3dCtor?: Maps3DCtor;\r\n private maps3dLayer?: IMaps3DLayer;\r\n private maps3dLayerReady = false;\r\n private maps3dLayerAttachPending = false;\r\n private buildingsEnabled = false;\r\n\r\n private constructor() {}\r\n\r\n private static getInstanceKey(options: IMahalMapOptions) {\r\n return typeof options.container === \"string\" && options.container\r\n ? options.container\r\n : \"map\";\r\n }\r\n\r\n private static normalizeLanguage(lang?: string | null): MapLanguage {\r\n return lang === \"ru\" ? \"ru\" : \"tj\";\r\n }\r\n\r\n static setDefaultLanguage(lang?: string | null) {\r\n MahalMap.defaultLanguage = MahalMap.normalizeLanguage(lang);\r\n }\r\n\r\n private static getDefaultStyle(theme: Theme, lang: MapLanguage) {\r\n return buildStyleUrl(defaultStyles[theme], lang, MahalMap.getMapToken());\r\n }\r\n\r\n private static getVectorStyle() {\r\n return buildStyleUrl(VECTOR, undefined, MahalMap.getMapToken());\r\n }\r\n\r\n private static getMapToken() {\r\n const token = getApiKey();\r\n\r\n if (!token) {\r\n throw new Error(\r\n \"[MahalMap SDK] Map API key is required. Call keyUtils.saveKey() before creating the map or pass apikey in the SDK script URL.\",\r\n );\r\n }\r\n\r\n return token;\r\n }\r\n\r\n private static getMaps3DCtor(explicit?: Maps3DCtor): Maps3DCtor | undefined {\r\n if (explicit) {\r\n return explicit;\r\n }\r\n\r\n if (typeof window === \"undefined\") {\r\n return undefined;\r\n }\r\n\r\n // IIFE global build (maps3d.global.js, global-name=Maps3D) exposes a\r\n // namespace object { Maps3D: ctor }, not the constructor itself.\r\n const globalNs = (\r\n window as unknown as { Maps3D?: Maps3DCtor | { Maps3D?: Maps3DCtor } }\r\n ).Maps3D;\r\n\r\n if (typeof globalNs === \"function\") {\r\n return globalNs;\r\n }\r\n\r\n return globalNs?.Maps3D;\r\n }\r\n\r\n static create(\r\n options: IMahalMapOptions,\r\n maplibreObject?: MapLibreApi,\r\n maps3dCtor?: Maps3DCtor,\r\n ) {\r\n const globalMaplibre =\r\n typeof window !== \"undefined\"\r\n ? (window as unknown as { maplibregl?: MapLibreApi }).maplibregl\r\n : undefined;\r\n const maplibre = globalMaplibre || maplibreObject;\r\n\r\n if (!maplibre) {\r\n throw new Error(\r\n \"[MahalMap SDK] MapLibre GL was not found. Pass it as the second argument or include it through a script.\",\r\n );\r\n }\r\n\r\n const language = MahalMap.normalizeLanguage(\r\n options.lang || MahalMap.defaultLanguage,\r\n );\r\n const theme = options.theme === \"dark\" ? \"dark\" : \"light\";\r\n const engine: MapEngine = options.engine === \"3d\" ? \"3d\" : \"legacy\";\r\n\r\n const instance = new MahalMap();\r\n const instanceKey = MahalMap.getInstanceKey(options);\r\n\r\n instance.options = options;\r\n instance.language = language;\r\n instance.instanceKey = instanceKey;\r\n instance.maplibre = maplibre;\r\n instance.engine = engine;\r\n\r\n if (engine === \"3d\") {\r\n // 3D включен по умолчанию для engine:\"3d\", пока явно не выключен (enable3D: false).\r\n const enable3D = options.enable3D !== false;\r\n\r\n instance.buildingsEnabled = enable3D;\r\n instance.gramBase = options.base || GRAM_BASE;\r\n instance.presetIsExplicit = Boolean(options.preset);\r\n instance.gramPreset = options.preset || GRAM_PRESETS[theme];\r\n instance.maps3dCtor = MahalMap.getMaps3DCtor(maps3dCtor);\r\n\r\n const finalStyle = options.style\r\n ? options.style\r\n : buildGramStyleUrl(instance.gramBase, instance.gramPreset);\r\n\r\n const transformRequest = instance.maps3dCtor\r\n ? instance.maps3dCtor.transformRequest({\r\n base: instance.gramBase,\r\n apiKey: getApiKey() || undefined,\r\n })\r\n : undefined;\r\n\r\n // Без наклона камеры (pitch) экструзия зданий не видна — вид строго сверху.\r\n const defaultPitch = enable3D ? 58 : 0;\r\n\r\n instance.map = new maplibre.Map({\r\n container: options.container || \"map\",\r\n style: finalStyle,\r\n center: options.center || [69.624024, 40.279687],\r\n zoom: options.zoom || 5,\r\n attributionControl: false,\r\n pitch: options.pitch !== undefined ? options.pitch : defaultPitch,\r\n ...(options.bearing !== undefined ? { bearing: options.bearing } : {}),\r\n ...(transformRequest ? { transformRequest } : {}),\r\n } as ConstructorParameters<typeof MapType>[0]);\r\n\r\n if (enable3D) {\r\n if (!instance.maps3dCtor) {\r\n throw new Error(\r\n \"[MahalMap SDK] Maps3D was not found. Pass it as the third argument to create() or include it through a script (window.Maps3D).\",\r\n );\r\n }\r\n\r\n instance.maps3dLayer = new instance.maps3dCtor({\r\n apiKey: getApiKey() || undefined,\r\n base: instance.gramBase,\r\n buildings: true,\r\n ...options.maps3d,\r\n });\r\n instance.attachMaps3DLayer(instance.maps3dLayer);\r\n\r\n // Стили GramMaps несут свой fill-extrusion слой \"building-3d\" (плоские здания без окон).\r\n // Без скрытия он остаётся поверх/вместо процедурных Maps3D-зданий на каждой загрузке\r\n // стиля (в т.ч. после setStyle при смене темы) — визуально 3D не отличить от выключенного.\r\n instance.map.on(\"style.load\", () => {\r\n instance.setNativeBuildingsVisible(false);\r\n });\r\n }\r\n } else {\r\n const finalStyle = options.autoAddVectorSource\r\n ? MahalMap.getVectorStyle()\r\n : options.style\r\n ? options.style\r\n : MahalMap.getDefaultStyle(theme, language);\r\n\r\n instance.map = new maplibre.Map({\r\n container: options.container || \"map\",\r\n style: finalStyle as string,\r\n center: options.center || [69.624024, 40.279687],\r\n zoom: options.zoom || 5,\r\n attributionControl: false,\r\n ...(options.pitch !== undefined ? { pitch: options.pitch } : {}),\r\n ...(options.bearing !== undefined ? { bearing: options.bearing } : {}),\r\n });\r\n }\r\n\r\n instance.addLogo(theme);\r\n\r\n instance.map.on(\"load\", () => {\r\n instance.isReady = true;\r\n\r\n instance.camera = new CameraController(instance.map);\r\n\r\n instance.readyCallbacks.forEach((cb) => cb(instance.map));\r\n instance.readyCallbacks = [];\r\n });\r\n\r\n MahalMap.instances.set(instanceKey, instance);\r\n return instance;\r\n }\r\n\r\n static onReady(container: string, callback: (map: MapType) => void) {\r\n if (!MahalMap.instances.has(container)) {\r\n const check = setInterval(() => {\r\n if (MahalMap.instances.has(container)) {\r\n clearInterval(check);\r\n MahalMap.onReady(container, callback);\r\n }\r\n }, 50);\r\n return;\r\n }\r\n\r\n const instance = MahalMap.getInstance(container);\r\n\r\n if (instance.isReady) {\r\n callback(instance.map);\r\n } else {\r\n instance.readyCallbacks.push(callback);\r\n }\r\n }\r\n\r\n static getInstance(container: string): MahalMap {\r\n const instance = MahalMap.instances.get(container);\r\n\r\n if (!instance) {\r\n throw new Error(\"[MahalMap SDK] Map instance is not created\");\r\n }\r\n\r\n return instance;\r\n }\r\n\r\n static hasInstance(container: string): boolean {\r\n return MahalMap.instances.has(container);\r\n }\r\n\r\n static removeInstance(container: string): boolean {\r\n return MahalMap.instances.delete(container);\r\n }\r\n\r\n static addMarker(instance: MahalMap, marker: IMapMarker) {\r\n return instance.addMarker(marker);\r\n }\r\n\r\n static getCamera(instance: MahalMap) {\r\n return instance.getCamera();\r\n }\r\n\r\n static getMap(instance: MahalMap): MapType {\r\n return instance.getMap();\r\n }\r\n\r\n static setStyle(instance: MahalMap, theme: Theme) {\r\n instance.setStyle(theme);\r\n }\r\n\r\n static getMaps3DLayer(instance: MahalMap) {\r\n return instance.getMaps3DLayer();\r\n }\r\n\r\n static toggle3DBuildings(instance: MahalMap, enabled: boolean) {\r\n instance.toggle3DBuildings(enabled);\r\n }\r\n\r\n static setLanguage(instance: MahalMap, lang: MapLanguage) {\r\n instance.setLanguage(lang);\r\n }\r\n\r\n static setCenter(instance: MahalMap, center: [number, number]) {\r\n instance.setCenter(center);\r\n }\r\n\r\n static setZoom(instance: MahalMap, zoom: number) {\r\n instance.setZoom(zoom);\r\n }\r\n\r\n static destroy(instance: MahalMap) {\r\n instance.destroy();\r\n }\r\n\r\n addMarker(marker: IMapMarker) {\r\n return addMarker(this.maplibre, this.map, marker);\r\n }\r\n\r\n init(map: MapType) {\r\n this.map = map;\r\n this.camera = new CameraController(map);\r\n }\r\n\r\n getCamera() {\r\n return this.camera;\r\n }\r\n\r\n getMap(): MapType {\r\n return this.map;\r\n }\r\n\r\n setStyle(theme: Theme) {\r\n this.options.theme = theme;\r\n\r\n if (this.engine === \"3d\") {\r\n if (this.options.style || this.presetIsExplicit) {\r\n return;\r\n }\r\n\r\n this.gramPreset = GRAM_PRESETS[theme];\r\n this.map.setStyle(buildGramStyleUrl(this.gramBase, this.gramPreset));\r\n this.updateLogoColor(theme);\r\n return;\r\n }\r\n\r\n if (this.options.autoAddVectorSource) {\r\n return;\r\n }\r\n\r\n if (!this.options.style) {\r\n this.map.setStyle(MahalMap.getDefaultStyle(theme, this.language));\r\n }\r\n\r\n this.updateLogoColor(theme);\r\n }\r\n\r\n setLanguage(lang: MapLanguage) {\r\n this.language = MahalMap.normalizeLanguage(lang);\r\n this.options.lang = this.language;\r\n\r\n if (\r\n this.engine === \"3d\" ||\r\n this.options.autoAddVectorSource ||\r\n this.options.style\r\n ) {\r\n return;\r\n }\r\n\r\n const theme = this.options.theme === \"dark\" ? \"dark\" : \"light\";\r\n this.map.setStyle(MahalMap.getDefaultStyle(theme, this.language));\r\n }\r\n\r\n getMaps3DLayer(): IMaps3DLayer | undefined {\r\n return this.maps3dLayer;\r\n }\r\n\r\n /** Вкл/выкл детальные 3D-здания (Maps3D). Работает только для engine: \"3d\". */\r\n toggle3DBuildings(enabled: boolean) {\r\n if (this.engine !== \"3d\") {\r\n return;\r\n }\r\n\r\n this.buildingsEnabled = enabled;\r\n this.setNativeBuildingsVisible(!enabled);\r\n\r\n if (!this.maps3dLayer) {\r\n if (!enabled || !this.maps3dCtor) {\r\n return;\r\n }\r\n\r\n this.maps3dLayer = new this.maps3dCtor({\r\n apiKey: getApiKey() || undefined,\r\n base: this.gramBase,\r\n buildings: true,\r\n ...this.options.maps3d,\r\n });\r\n this.attachMaps3DLayer(this.maps3dLayer);\r\n return;\r\n }\r\n\r\n if (this.maps3dLayer.setBuildingsEnabled) {\r\n this.applyMaps3DBuildingMode(enabled);\r\n return;\r\n }\r\n\r\n if (!enabled) {\r\n this.maps3dLayer.destroy?.();\r\n this.maps3dLayer.remove?.();\r\n this.maps3dLayer = undefined;\r\n this.maps3dLayerReady = false;\r\n }\r\n }\r\n\r\n private attachMaps3DLayer(layer: IMaps3DLayer) {\r\n this.maps3dLayerAttachPending = true;\r\n this.maps3dLayerReady = false;\r\n\r\n void Promise.resolve(layer.attach(this.map))\r\n .then(() => {\r\n if (this.maps3dLayer !== layer) {\r\n return;\r\n }\r\n\r\n this.maps3dLayerReady = true;\r\n this.maps3dLayerAttachPending = false;\r\n this.applyMaps3DBuildingMode(this.buildingsEnabled);\r\n })\r\n .catch((error: unknown) => {\r\n if (this.maps3dLayer === layer) {\r\n this.maps3dLayer = undefined;\r\n }\r\n\r\n this.maps3dLayerReady = false;\r\n this.maps3dLayerAttachPending = false;\r\n this.buildingsEnabled = false;\r\n this.setNativeBuildingsVisible(true);\r\n console.error(\"[MahalMap SDK] Failed to attach Maps3D layer\", error);\r\n });\r\n }\r\n\r\n private applyMaps3DBuildingMode(enabled: boolean) {\r\n if (!this.maps3dLayer) {\r\n return;\r\n }\r\n\r\n this.maps3dLayer.setBuildingsEnabled?.(enabled);\r\n this.maps3dLayer.buildings?.setWindows?.(enabled);\r\n }\r\n\r\n /**\r\n * Прячет/показывает нативные здания стиля GramMaps (\"building-3d\" и любые fill-extrusion /\r\n * fill+source-layer=building), не задевая слои самого Maps3D. Нужно, иначе плоский слой стиля\r\n * рисуется поверх процедурных 3D-зданий и визуально их перекрывает.\r\n */\r\n private setNativeBuildingsVisible(visible: boolean) {\r\n const layers = this.map.getStyle()?.layers || [];\r\n\r\n for (const layer of layers) {\r\n const isMaps3DLayer = layer.id.startsWith(\"maps3d-\");\r\n const isBuildingLayer =\r\n layer.type === \"fill-extrusion\" ||\r\n (\"source-layer\" in layer &&\r\n layer.type === \"fill\" &&\r\n layer[\"source-layer\"] === \"building\");\r\n\r\n if (isMaps3DLayer || !isBuildingLayer) {\r\n continue;\r\n }\r\n\r\n try {\r\n this.map.setLayoutProperty(\r\n layer.id,\r\n \"visibility\",\r\n visible ? \"visible\" : \"none\",\r\n );\r\n } catch {\r\n // слой мог исчезнуть при смене стиля — не критично\r\n }\r\n }\r\n }\r\n\r\n setCenter(center: [number, number]) {\r\n this.map.setCenter(center);\r\n }\r\n\r\n setZoom(zoom: number) {\r\n this.map.setZoom(zoom);\r\n }\r\n\r\n destroy() {\r\n this.maps3dLayer?.destroy?.();\r\n this.maps3dLayer?.remove?.();\r\n this.maps3dLayer = undefined;\r\n this.maps3dLayerReady = false;\r\n this.maps3dLayerAttachPending = false;\r\n this.logoObserver?.disconnect();\r\n this.logoObserver = undefined;\r\n this.logoHost?.remove();\r\n this.logoHost = undefined;\r\n this.logoShadow = undefined;\r\n this.map.remove();\r\n MahalMap.instances.delete(this.instanceKey);\r\n }\r\n\r\n private addLogo(theme: \"dark\" | \"light\") {\r\n const container = this.map.getContainer();\r\n const logoHost = document.createElement(\"div\");\r\n const logoShadow = logoHost.attachShadow({ mode: \"closed\" });\r\n\r\n logoHost.setAttribute(\"aria-label\", \"Mahal\");\r\n logoHost.dataset.mahal = Math.random().toString(36).slice(2);\r\n this.logoHost = logoHost;\r\n this.logoShadow = logoShadow;\r\n\r\n this.applyLogoHostStyles();\r\n this.renderLogo(theme);\r\n container.appendChild(logoHost);\r\n this.observeLogo(container);\r\n }\r\n\r\n private updateLogoColor(theme: \"dark\" | \"light\") {\r\n if (!this.logoShadow) {\r\n return;\r\n }\r\n\r\n this.renderLogo(theme);\r\n }\r\n\r\n private renderLogo(theme: \"dark\" | \"light\") {\r\n if (!this.logoShadow) {\r\n return;\r\n }\r\n\r\n this.logoShadow.innerHTML = `\r\n <style>\r\n :host {\r\n all: initial;\r\n }\r\n\r\n .logo-wrap {\r\n display: block;\r\n width: 80px;\r\n height: 18.45px;\r\n line-height: 0;\r\n pointer-events: none;\r\n user-select: none;\r\n }\r\n\r\n svg {\r\n display: block;\r\n }\r\n </style>\r\n <span class=\"logo-wrap\" aria-hidden=\"true\">\r\n ${this.getLogoSvg(logoColors[theme])}\r\n </span>\r\n `;\r\n }\r\n\r\n private applyLogoHostStyles() {\r\n if (!this.logoHost) {\r\n return;\r\n }\r\n\r\n const style = this.logoHost.style;\r\n\r\n style.setProperty(\"position\", \"absolute\", \"important\");\r\n style.setProperty(\"right\", \"10px\", \"important\");\r\n style.setProperty(\"bottom\", \"10px\", \"important\");\r\n style.setProperty(\"z-index\", \"1\", \"important\");\r\n style.setProperty(\"display\", \"block\", \"important\");\r\n style.setProperty(\"visibility\", \"visible\", \"important\");\r\n style.setProperty(\"opacity\", \"1\", \"important\");\r\n style.setProperty(\"pointer-events\", \"none\", \"important\");\r\n style.setProperty(\"line-height\", \"0\", \"important\");\r\n style.setProperty(\"width\", \"80px\", \"important\");\r\n style.setProperty(\"height\", \"18.45px\", \"important\");\r\n }\r\n\r\n private observeLogo(container: HTMLElement) {\r\n if (!this.logoHost) {\r\n return;\r\n }\r\n\r\n this.logoObserver?.disconnect();\r\n this.logoObserver = new MutationObserver(() => {\r\n if (!this.logoHost) {\r\n return;\r\n }\r\n\r\n this.applyLogoHostStyles();\r\n\r\n if (!container.contains(this.logoHost)) {\r\n container.appendChild(this.logoHost);\r\n }\r\n });\r\n\r\n this.logoObserver.observe(container, { childList: true });\r\n this.logoObserver.observe(this.logoHost, {\r\n attributes: true,\r\n attributeFilter: [\"class\", \"style\", \"hidden\"],\r\n });\r\n }\r\n\r\n private getLogoSvg(color: string) {\r\n return `\r\n <svg class=\"logo\" width=\"80\" viewBox=\"0 0 143 33\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" style=\"opacity: 0.95;\">\r\n <g clip-path=\"url(#mahal-logo-text)\">\r\n <path d=\"M57.2317 27.0218H52.8158V17.4678C52.8522 16.33 52.5154 15.2116 51.8567 14.2832C51.5507 13.8592 51.1439 13.5179 50.6731 13.2903C50.2023 13.0627 49.6822 12.9558 49.1598 12.9793C48.6266 12.9617 48.0969 13.0725 47.6154 13.3022C47.1338 13.532 46.7145 13.874 46.3926 14.2995C45.6965 15.2066 45.3323 16.3248 45.3607 17.4678V27.0218H40.9472V9.14261H45.0371L45.3631 11.3142C45.7779 10.4819 46.4682 9.81897 47.3166 9.4381C48.1797 9.04305 49.1182 8.83982 50.0674 8.84243C52.6721 8.84243 54.4332 9.9525 55.3509 12.1726C56.7283 10.001 58.7194 8.91514 61.324 8.91514C63.8255 8.91514 65.7133 9.6445 66.9875 11.1032C68.2617 12.5618 68.8949 14.6553 68.8871 17.3834V27.0102H64.4688V17.3952C64.4688 16.1178 64.1913 15.0742 63.6363 14.2644C63.0813 13.4545 62.2371 13.0504 61.1036 13.052C60.5671 13.0338 60.0336 13.1404 59.5453 13.3634C59.0569 13.5864 58.6271 13.9197 58.2894 14.3371C57.5684 15.2182 57.1895 16.3298 57.2223 17.4678L57.2317 27.0218Z\" fill=\"${color}\" />\r\n <path d=\"M87.3807 11.6402L87.5261 9.18015H91.7614V27.0218H87.5988L87.3807 24.4164C86.851 25.4268 85.997 26.2296 84.9559 26.6959C83.911 27.2275 82.7623 27.5237 81.5906 27.5636C78.8656 27.587 76.6525 26.7725 74.9516 25.12C73.2506 23.4674 72.4001 21.1223 72.4001 18.0846C72.4001 15.1141 73.2748 12.8096 75.0243 11.1712C76.7737 9.5327 78.9992 8.72439 81.7008 8.74628C82.8702 8.73859 84.0244 9.01209 85.066 9.54366C86.0248 10.0029 86.8291 10.7314 87.3807 11.6402ZM82.0972 12.6908C81.4026 12.6688 80.7104 12.7854 80.0614 13.0339C79.4123 13.2823 78.8193 13.6575 78.3168 14.1377C77.3162 15.1008 76.8151 16.4156 76.8136 18.0822C76.812 19.7488 77.3131 21.0699 78.3168 22.0455C78.8166 22.5305 79.4089 22.9103 80.0583 23.162C80.7077 23.4138 81.401 23.5325 82.0972 23.5112C83.3119 23.549 84.4998 23.1505 85.446 22.3879C86.304 21.7164 86.8944 20.761 87.111 19.6933C87.3151 18.6471 87.3151 17.5713 87.111 16.525C86.8973 15.451 86.3068 14.4887 85.446 13.8118C84.4984 13.0487 83.3085 12.651 82.0925 12.6908H82.0972Z\" fill=\"${color}\" />\r\n <path d=\"M95.483 1.6875H99.8989V11.605C101.273 9.818 103.131 8.92531 105.471 8.92687C107.933 8.92687 109.767 9.69295 110.973 11.2251C112.178 12.7572 112.781 14.8858 112.781 17.6109V27.0218H108.367V17.6413C108.367 16.0779 107.999 14.914 107.263 14.1495C106.526 13.385 105.543 13.0042 104.313 13.0074C103.714 12.9928 103.119 13.1115 102.571 13.3548C102.024 13.5982 101.537 13.9601 101.147 14.4144C100.308 15.3743 99.862 16.6156 99.8989 17.8899V27.0101H95.483V1.6875Z\" fill=\"${color}\" />\r\n <path d=\"M130.515 11.6402L130.66 9.18015H134.893V27.0218H130.733L130.515 24.4164C129.984 25.4263 129.13 26.229 128.09 26.6959C127.045 27.2273 125.896 27.5235 124.724 27.5636C121.998 27.587 119.784 26.7725 118.083 25.12C116.382 23.4674 115.532 21.1223 115.532 18.0846C115.532 15.1141 116.406 12.8096 118.156 11.1712C119.905 9.5327 122.131 8.72439 124.832 8.74628C126.002 8.73804 127.156 9.01157 128.198 9.54366C129.157 10.0029 129.962 10.7313 130.515 11.6402ZM125.231 12.6908C124.536 12.6688 123.844 12.7853 123.194 13.0337C122.545 13.2822 121.951 13.6575 121.448 14.1377C120.446 15.1008 119.946 16.4156 119.947 18.0822C119.949 19.7488 120.449 21.0699 121.448 22.0455C121.949 22.5306 122.541 22.9103 123.191 23.1621C123.841 23.4139 124.534 23.5326 125.231 23.5112C126.445 23.5495 127.632 23.1509 128.577 22.3879C129.436 21.7171 130.027 20.7614 130.243 19.6933C130.447 18.6471 130.447 17.5713 130.243 16.525C130.03 15.4506 129.439 14.488 128.577 13.8118C127.632 13.0494 126.445 12.6516 125.231 12.6908Z\" fill=\"${color}\" />\r\n <path d=\"M138.622 1.72498H143V27.0218H138.622V1.72498Z\" fill=\"${color}\" />\r\n </g>\r\n <g clip-path=\"url(#mahal-logo-mark)\">\r\n <path d=\"M30.4142 14.0273H22.0831L27.974 8.1364C28.4165 7.69383 28.6651 7.09361 28.665 6.46779C28.6649 5.84197 28.4163 5.2418 27.9737 4.79932C27.5311 4.35684 26.9309 4.10829 26.3051 4.10835C25.6793 4.10841 25.0791 4.35708 24.6366 4.79965L18.7463 10.6906V2.35952C18.7463 1.73373 18.4978 1.13358 18.0553 0.691086C17.6128 0.248591 17.0126 0 16.3868 0C15.761 0 15.1609 0.248591 14.7184 0.691086C14.2759 1.13358 14.0273 1.73373 14.0273 2.35952V10.6906L8.13639 4.79965C7.69268 4.3631 7.09445 4.11958 6.472 4.12211C5.84955 4.12465 5.25332 4.37304 4.81318 4.81318C4.37304 5.25332 4.12465 5.84955 4.12211 6.472C4.11958 7.09445 4.3631 7.69268 4.79965 8.1364L10.6906 14.0273H2.35952C1.73373 14.0273 1.13358 14.2759 0.691084 14.7184C0.248589 15.1609 0 15.7611 0 16.3868C0 17.0126 0.248589 17.6128 0.691084 18.0553C1.13358 18.4978 1.73373 18.7464 2.35952 18.7464H10.6906L4.79965 24.6373C4.3631 25.081 4.11958 25.6792 4.12211 26.3017C4.12465 26.9241 4.37304 27.5203 4.81318 27.9605C5.25332 28.4006 5.84955 28.649 6.472 28.6516C7.09445 28.6541 7.69268 28.4106 8.13639 27.974L14.0273 22.0831V30.4142C14.0273 31.0399 14.2759 31.6401 14.7184 32.0826C15.1609 32.5251 15.761 32.7737 16.3868 32.7737C17.0126 32.7737 17.6128 32.5251 18.0553 32.0826C18.4978 31.6401 18.7463 31.0399 18.7463 30.4142V22.0831L24.6366 27.974C25.0791 28.4166 25.6793 28.6653 26.3051 28.6653C26.9309 28.6654 27.5311 28.4168 27.9737 27.9743C28.4163 27.5319 28.6649 26.9317 28.665 26.3059C28.6651 25.6801 28.4165 25.0798 27.974 24.6373L22.0831 18.7464H30.4142C31.0399 18.7464 31.6401 18.4978 32.0826 18.0553C32.5251 17.6128 32.7737 17.0126 32.7737 16.3868C32.7737 15.7611 32.5251 15.1609 32.0826 14.7184C31.6401 14.2759 31.0399 14.0273 30.4142 14.0273Z\" fill=\"#278960\" />\r\n </g>\r\n <defs>\r\n <clipPath id=\"mahal-logo-text\">\r\n <rect width=\"102.055\" height=\"25.8761\" fill=\"white\" transform=\"translate(40.9449 1.6875)\" />\r\n </clipPath>\r\n <clipPath id=\"mahal-logo-mark\">\r\n <rect width=\"32.7737\" height=\"32.7737\" fill=\"white\" />\r\n </clipPath>\r\n </defs>\r\n </svg>\r\n `;\r\n }\r\n}\r\n","export * from \"./authKey\";\nexport * from \"./routing\";\nexport * from \"./search\";\n","import axios from \"axios\";\r\nimport { BASE_URL } from \"@config\";\r\n\r\nexport const api = axios.create({\r\n baseURL: BASE_URL,\r\n});\r\n","import { api } from \"../httpClient\";\r\n\r\nconst routingApi = async (param: number[][], token: string) => {\r\n try {\r\n const points: { lng: number; lat: number }[] = [];\r\n\r\n param.forEach((e) => {\r\n points.push({ lng: e[0], lat: e[1] });\r\n });\r\n const response = await api.post(\"services/getRoutes\", {\r\n points,\r\n token,\r\n });\r\n return response.data;\r\n } catch (err) {\r\n console.error(err);\r\n throw err;\r\n }\r\n};\r\n\r\nexport { routingApi };\r\n","export * from \"./coordinates\";\r\nexport * from \"./debounce\";\r\nexport * from \"./polyline\";\r\nexport * from \"./trimValue\";\r\n","import { LATLNGREGEX, LNGLATREGEX } from \"@config\";\r\n\r\nexport function checkCoordinates(coordinates: string) {\r\n let lat, lng;\r\n if (LATLNGREGEX.test(coordinates)) {\r\n const match = coordinates.match(LATLNGREGEX);\r\n if (match) {\r\n [, lat, lng] = match; // Первый элемент — полное совпадение, пропускаем его\r\n }\r\n } else if (LNGLATREGEX.test(coordinates)) {\r\n const match = coordinates.match(LNGLATREGEX);\r\n if (match) {\r\n [, lng, lat] = match; // Меняем местами\r\n }\r\n } else {\r\n console.log(\"Неверный формат координат\");\r\n return null;\r\n }\r\n return { lat, lng };\r\n}\r\n","function debounce<F extends (...args: any[]) => Promise<any>>(\r\n fn: F,\r\n delay: number,\r\n) {\r\n let timer: ReturnType<typeof setTimeout>;\r\n\r\n return (...args: Parameters<F>): Promise<ReturnType<F>> => {\r\n if (timer) clearTimeout(timer);\r\n return new Promise((resolve) => {\r\n timer = setTimeout(async () => {\r\n const result = await fn(...args);\r\n resolve(result);\r\n }, delay);\r\n }) as Promise<ReturnType<F>>;\r\n };\r\n}\r\n\r\nexport { debounce };\r\n","function geojsonPolyline(encoded: string): number[][] {\r\n let points = [];\r\n let index = 0,\r\n len = encoded.length;\r\n let lat = 0,\r\n lng = 0;\r\n\r\n while (index < len) {\r\n let b,\r\n shift = 0,\r\n result = 0;\r\n do {\r\n b = encoded.charCodeAt(index++) - 63;\r\n result |= (b & 0x1f) << shift;\r\n shift += 5;\r\n } while (b >= 0x20);\r\n let dlat = result & 1 ? ~(result >> 1) : result >> 1;\r\n lat += dlat;\r\n\r\n shift = 0;\r\n result = 0;\r\n do {\r\n b = encoded.charCodeAt(index++) - 63;\r\n result |= (b & 0x1f) << shift;\r\n shift += 5;\r\n } while (b >= 0x20);\r\n let dlng = result & 1 ? ~(result >> 1) : result >> 1;\r\n lng += dlng;\r\n\r\n points.push([lng * 1e-5, lat * 1e-5]);\r\n }\r\n\r\n return points;\r\n}\r\n\r\nexport { geojsonPolyline };\r\n\r\n// Пример использования:\r\n\r\n// geojsonPolyline(\"yzocFzynhVq}@n}@o}@nzD\")\r\n\r\n// Вернёт массив вида [\r\n// [102.0, 0.5],\r\n// [103.0, 1.0],\r\n// [104.0, 0.5],\r\n// [105.0, 0.0]\r\n// ].\r\n","function geometryPolyline(coordinates: number[][]): string {\r\n let encoded = '';\r\n let prevLat = 0;\r\n let prevLng = 0;\r\n\r\n for (let i = 0; i < coordinates.length; i++) {\r\n const [lng, lat] = coordinates[i];\r\n \r\n // Умножаем координаты на 1e5 и округляем\r\n const latE5 = Math.round(lat * 1e5);\r\n const lngE5 = Math.round(lng * 1e5);\r\n\r\n // Вычисляем разницу от предыдущих значений\r\n const dLat = latE5 - prevLat;\r\n const dLng = lngE5 - prevLng;\r\n\r\n // Обновляем предыдущие значения\r\n prevLat = latE5;\r\n prevLng = lngE5;\r\n\r\n // Добавляем к закодированной строке\r\n encoded += encodeSignedNumber(dLat) + encodeSignedNumber(dLng);\r\n }\r\n\r\n return encoded;\r\n}\r\n\r\nfunction encodeSignedNumber(num: number) {\r\n let sgnNum = num << 1;\r\n if (num < 0) {\r\n sgnNum = ~sgnNum;\r\n }\r\n return encodeNumber(sgnNum);\r\n}\r\n\r\nfunction encodeNumber(num :number) {\r\n let encoded = '';\r\n while (num >= 0x20) {\r\n encoded += String.fromCharCode((0x20 | (num & 0x1f)) + 63);\r\n num >>= 5;\r\n }\r\n encoded += String.fromCharCode(num + 63);\r\n return encoded;\r\n}\r\n\r\nexport default geometryPolyline\r\n\r\n\r\n// Пример использования:\r\n\r\n// geometryPolyline([\r\n// [102.0, 0.5],\r\n// [103.0, 1.0],\r\n// [104.0, 0.5],\r\n// [105.0, 0.0]\r\n// ])\r\n\r\n// Вернёт строку вида \"yzocFzynhVq}@n}@o}@nzD\".","function trimValue(value: string, cut: number): string {\r\n if (cut <= 0) return \"\";\r\n\r\n // только обрезаем пробелы в начале и конце\r\n const cleanValue = value.trim();\r\n\r\n if (cut >= cleanValue.length) return cleanValue;\r\n\r\n return cleanValue.slice(0, cut);\r\n}\r\n\r\nexport { trimValue };\r\n","import { routingApi } from \"./routing.api\";\r\nimport { geojsonPolyline } from \"@utils\";\r\nimport type { IRoute } from \"@sdk-types\";\r\n\r\nasync function Router(\r\n param: number[][],\r\n typeData: string,\r\n token: string,\r\n): Promise<IRoute[]> {\r\n if (!token) {\r\n throw new Error(\"[MahalMap SDK] Router token is required\");\r\n }\r\n\r\n try {\r\n const res = await routingApi(param, token);\r\n\r\n if (!res?.data) return res;\r\n\r\n const data: IRoute[] = res.data;\r\n\r\n return data.map((route) => {\r\n const updated = { ...route };\r\n\r\n if (updated.route?.routes?.length) {\r\n updated.route.routes = updated.route.routes.map((r) => ({\r\n ...r,\r\n geometry:\r\n typeData === \"geojson\" && typeof r.geometry === \"string\"\r\n ? geojsonPolyline(r.geometry)\r\n : r.geometry,\r\n }));\r\n }\r\n\r\n return updated as IRoute;\r\n });\r\n } catch (error) {\r\n throw error;\r\n }\r\n}\r\n\r\nexport { Router };\r\n","import { api } from \"../httpClient\";\nimport type {\n ISearchByLocationParam,\n ISearchParam,\n ISearchResponse,\n IResponse,\n} from \"@sdk-types\";\n\nconst searchPost = async (params: ISearchParam) => {\n try {\n const response = await api.post<IResponse<ISearchResponse[]>>(\n \"services/getAddress\",\n null,\n {\n params,\n },\n );\n return response.data;\n } catch (error) {\n console.error(\"Error while searching address:\", error);\n throw error;\n }\n};\n\nconst searchByLocationPost = async (params: ISearchByLocationParam) => {\n try {\n const response = await api.post<IResponse<ISearchResponse[]>>(\n \"services/getAddressByLocation\",\n null,\n {\n params,\n },\n );\n return response.data;\n } catch (error) {\n console.error(\"Error while searching address by location:\", error);\n throw error;\n }\n};\n\nexport { searchPost, searchByLocationPost };\n","import { searchByLocationPost, searchPost } from \"./search.api\";\r\nimport {\r\n IAdditionalParamType,\r\n ISearchByLocationParam,\r\n ISearchParam,\r\n ISearchResponse,\r\n} from \"@sdk-types\";\r\nimport { debounce } from \"@utils\";\r\n// import { checkCoordinates } from \"@utils\";\r\n// import { REGEX } from \"@config\";\r\n\r\nasync function getSearch(\r\n param: string,\r\n token: string,\r\n additionalParam?: IAdditionalParamType,\r\n): Promise<ISearchResponse[]> {\r\n let searchData: ISearchParam = {\r\n text: param,\r\n token,\r\n ...additionalParam,\r\n };\r\n\r\n // if (param !== \"\") {\r\n // if (REGEX.test(param)) {\r\n // let coordinates = await checkCoordinates(param);\r\n // if (coordinates) {\r\n // searchData = {\r\n // lat: coordinates.lat ?? \"\",\r\n // lng: coordinates.lng ?? \"\",\r\n // };\r\n // }\r\n // } else {\r\n // searchData.text = param;\r\n // }\r\n // } else {\r\n // searchData.text = \"\";\r\n // }\r\n\r\n try {\r\n const res = await searchPost(searchData);\r\n return res.data;\r\n } catch (error) {\r\n throw error;\r\n }\r\n}\r\n\r\nconst debouncedFn = debounce(getSearch, 500);\r\n\r\nasync function Search(\r\n param: string,\r\n token: string,\r\n additionalParam?: IAdditionalParamType,\r\n): Promise<ISearchResponse[]> {\r\n if (!token) {\r\n throw new Error(\"[MahalMap SDK] Search token is required\");\r\n }\r\n\r\n return await debouncedFn(param, token, additionalParam);\r\n}\r\n\r\nasync function SearchByLocation(\r\n params: ISearchByLocationParam,\r\n): Promise<ISearchResponse> {\r\n if (!params.token) {\r\n throw new Error(\"[MahalMap SDK] SearchByLocation token is required\");\r\n }\r\n\r\n const searchData: ISearchByLocationParam = {\r\n ...params,\r\n };\r\n\r\n try {\r\n const res: any = await searchByLocationPost(searchData);\r\n return res;\r\n } catch (error) {\r\n throw error;\r\n }\r\n}\r\n\r\nexport { Search, SearchByLocation };\r\n","export * from \"./MeasureTool\";\r\nexport * from \"./geo\";\r\nexport * from \"./measure-type\";\r\n","const EARTH_RADIUS_M = 6371008.8;\r\n\r\nfunction toRadians(deg: number): number {\r\n return (deg * Math.PI) / 180;\r\n}\r\n\r\n/** Wraps a longitude delta (in degrees) into (-180, 180] so antimeridian crossings\r\n * (e.g. 179° -> -179°) are treated as a short ~2° step instead of a ~358° one. */\r\nfunction normalizeLngDeltaDeg(deltaDeg: number): number {\r\n return ((deltaDeg + 180) % 360 + 360) % 360 - 180;\r\n}\r\n\r\n/** Wraps a longitude (in degrees) into [-180, 180]. */\r\nfunction normalizeLngDeg(lngDeg: number): number {\r\n return ((lngDeg + 180) % 360 + 360) % 360 - 180;\r\n}\r\n\r\nexport function haversineDistance(\r\n a: [number, number],\r\n b: [number, number],\r\n): number {\r\n const [lng1, lat1] = a;\r\n const [lng2, lat2] = b;\r\n const phi1 = toRadians(lat1);\r\n const phi2 = toRadians(lat2);\r\n const deltaPhi = toRadians(lat2 - lat1);\r\n const deltaLambda = toRadians(lng2 - lng1);\r\n\r\n const sinDeltaPhi = Math.sin(deltaPhi / 2);\r\n const sinDeltaLambda = Math.sin(deltaLambda / 2);\r\n\r\n const centralAngleSegment =\r\n sinDeltaPhi * sinDeltaPhi +\r\n Math.cos(phi1) * Math.cos(phi2) * sinDeltaLambda * sinDeltaLambda;\r\n\r\n const centralAngle =\r\n 2 * Math.atan2(Math.sqrt(centralAngleSegment), Math.sqrt(1 - centralAngleSegment));\r\n\r\n return EARTH_RADIUS_M * centralAngle;\r\n}\r\n\r\nexport function lineLength(points: [number, number][]): number {\r\n let total = 0;\r\n\r\n for (let i = 1; i < points.length; i += 1) {\r\n total += haversineDistance(points[i - 1] as [number, number], points[i] as [number, number]);\r\n }\r\n\r\n return total;\r\n}\r\n\r\n/**\r\n * Spherical excess polygon area (same approach as Leaflet.GeometryUtil / turf's\r\n * geodesic area) — accurate enough for on-map measurement at city scale.\r\n */\r\nexport function polygonArea(points: [number, number][]): number {\r\n if (points.length < 3) {\r\n return 0;\r\n }\r\n\r\n let total = 0;\r\n\r\n for (let i = 0; i < points.length; i += 1) {\r\n const p1 = points[i] as [number, number];\r\n const p2 = points[(i + 1) % points.length] as [number, number];\r\n const deltaLambda = toRadians(normalizeLngDeltaDeg(p2[0] - p1[0]));\r\n const phi1 = toRadians(p1[1]);\r\n const phi2 = toRadians(p2[1]);\r\n\r\n total += deltaLambda * (2 + Math.sin(phi1) + Math.sin(phi2));\r\n }\r\n\r\n return Math.abs((total * EARTH_RADIUS_M * EARTH_RADIUS_M) / 2);\r\n}\r\n\r\nfunction vertexAverage(points: [number, number][]): [number, number] {\r\n const total = points.reduce(\r\n (acc, point) => [acc[0] + point[0], acc[1] + point[1]] as [number, number],\r\n [0, 0] as [number, number],\r\n );\r\n\r\n return [normalizeLngDeg(total[0] / points.length), total[1] / points.length];\r\n}\r\n\r\n/**\r\n * Area-weighted polygon centroid (shoelace-based), not a plain average of\r\n * vertices — a vertex average drifts outside the shape for concave or\r\n * unevenly-spaced polygons. Longitudes are unwrapped relative to the first\r\n * point first so shapes crossing the antimeridian don't collapse toward 0.\r\n */\r\nexport function polygonCentroid(points: [number, number][]): [number, number] {\r\n if (points.length === 0) {\r\n return [0, 0];\r\n }\r\n\r\n if (points.length < 3) {\r\n return vertexAverage(points);\r\n }\r\n\r\n const referenceLng = points[0]?.[0] ?? 0;\r\n const unwrapped = points.map(\r\n ([lng, lat]) => [referenceLng + normalizeLngDeltaDeg(lng - referenceLng), lat] as [number, number],\r\n );\r\n\r\n let signedAreaSum = 0;\r\n let cxSum = 0;\r\n let cySum = 0;\r\n\r\n for (let i = 0; i < unwrapped.length; i += 1) {\r\n const [x0, y0] = unwrapped[i] as [number, number];\r\n const [x1, y1] = unwrapped[(i + 1) % unwrapped.length] as [number, number];\r\n const cross = x0 * y1 - x1 * y0;\r\n\r\n signedAreaSum += cross;\r\n cxSum += (x0 + x1) * cross;\r\n cySum += (y0 + y1) * cross;\r\n }\r\n\r\n const signedArea = signedAreaSum / 2;\r\n\r\n // Degenerate polygon (collinear/duplicate points, zero area) — the shoelace\r\n // formula divides by zero here, fall back to a plain vertex average.\r\n if (Math.abs(signedArea) < 1e-12) {\r\n return vertexAverage(unwrapped);\r\n }\r\n\r\n const centroidLng = cxSum / (6 * signedArea);\r\n const centroidLat = cySum / (6 * signedArea);\r\n\r\n return [normalizeLngDeg(centroidLng), centroidLat];\r\n}\r\n\r\n/**\r\n * True midpoint along the line by cumulative length (not a vertex) — for an\r\n * uneven polyline the point at index Math.floor(n/2) can sit far from the\r\n * geometric middle. Longitude interpolation is antimeridian-aware.\r\n */\r\nexport function midpoint(points: [number, number][]): [number, number] {\r\n if (points.length === 0) {\r\n return [0, 0];\r\n }\r\n\r\n if (points.length === 1) {\r\n return points[0] as [number, number];\r\n }\r\n\r\n const segmentLengths: number[] = [];\r\n let totalLength = 0;\r\n\r\n for (let i = 1; i < points.length; i += 1) {\r\n const length = haversineDistance(points[i - 1] as [number, number], points[i] as [number, number]);\r\n segmentLengths.push(length);\r\n totalLength += length;\r\n }\r\n\r\n if (totalLength === 0) {\r\n return points[0] as [number, number];\r\n }\r\n\r\n const targetLength = totalLength / 2;\r\n let traversed = 0;\r\n\r\n for (let i = 1; i < points.length; i += 1) {\r\n const segmentLength = segmentLengths[i - 1] as number;\r\n\r\n if (traversed + segmentLength >= targetLength) {\r\n const t = segmentLength === 0 ? 0 : (targetLength - traversed) / segmentLength;\r\n const a = points[i - 1] as [number, number];\r\n const b = points[i] as [number, number];\r\n const lng = normalizeLngDeg(a[0] + normalizeLngDeltaDeg(b[0] - a[0]) * t);\r\n const lat = a[1] + (b[1] - a[1]) * t;\r\n\r\n return [lng, lat];\r\n }\r\n\r\n traversed += segmentLength;\r\n }\r\n\r\n return points[points.length - 1] as [number, number];\r\n}\r\n","// Strict allowlist: only static, non-referencing shape primitives are kept.\r\n// Anything capable of loading external resources, running script, or\r\n// animating (SMIL) is dropped by omission — this is a default-deny sanitizer,\r\n// not a denylist, so unknown/future attack surface is excluded by default.\r\nconst ALLOWED_TAGS = new Set([\r\n \"svg\",\r\n \"g\",\r\n \"path\",\r\n \"circle\",\r\n \"ellipse\",\r\n \"rect\",\r\n \"line\",\r\n \"polyline\",\r\n \"polygon\",\r\n]);\r\n\r\nconst ALLOWED_ATTRS = new Set([\r\n \"xmlns\",\r\n \"viewbox\",\r\n \"width\",\r\n \"height\",\r\n \"fill\",\r\n \"fill-rule\",\r\n \"fill-opacity\",\r\n \"stroke\",\r\n \"stroke-width\",\r\n \"stroke-linecap\",\r\n \"stroke-linejoin\",\r\n \"stroke-dasharray\",\r\n \"stroke-opacity\",\r\n \"opacity\",\r\n \"d\",\r\n \"cx\",\r\n \"cy\",\r\n \"r\",\r\n \"rx\",\r\n \"ry\",\r\n \"x\",\r\n \"y\",\r\n \"x1\",\r\n \"y1\",\r\n \"x2\",\r\n \"y2\",\r\n \"points\",\r\n \"transform\",\r\n]);\r\n\r\n// Presentation attributes that could otherwise carry a url(...) reference\r\n// (gradients/patterns/filters aren't in ALLOWED_TAGS, so any url() here is\r\n// either dead or an attempt to reach outside the document — reject either way).\r\nconst URL_SENSITIVE_ATTRS = new Set([\"fill\", \"stroke\"]);\r\n\r\nfunction isSafeValue(attrName: string, value: string): boolean {\r\n const normalized = value.trim().toLowerCase();\r\n\r\n if (normalized.includes(\"javascript:\") || normalized.includes(\"data:\") || normalized.includes(\"expression(\")) {\r\n return false;\r\n }\r\n\r\n if (URL_SENSITIVE_ATTRS.has(attrName) && normalized.includes(\"url(\")) {\r\n return false;\r\n }\r\n\r\n return true;\r\n}\r\n\r\nfunction sanitizeElement(element: Element): boolean {\r\n if (!ALLOWED_TAGS.has(element.tagName.toLowerCase())) {\r\n return false;\r\n }\r\n\r\n Array.from(element.attributes).forEach((attribute) => {\r\n const name = attribute.name.toLowerCase();\r\n\r\n if (!ALLOWED_ATTRS.has(name) || !isSafeValue(name, attribute.value)) {\r\n element.removeAttribute(attribute.name);\r\n }\r\n });\r\n\r\n Array.from(element.children).forEach((child) => {\r\n if (!sanitizeElement(child)) {\r\n child.remove();\r\n }\r\n });\r\n\r\n return true;\r\n}\r\n\r\n/**\r\n * Rebuilds an SVG icon from scratch using a strict tag/attribute allowlist\r\n * before it is inserted via innerHTML. Consumers may pass arbitrary icon\r\n * markup through MeasureIcons, so nothing outside static shape primitives\r\n * (path/circle/rect/line/polyline/polygon/g) survives — no <script>, <use>,\r\n * <image>, <a>, <style>, or SMIL (<animate>/<set>), and no url(...)/javascript:/\r\n * data: values on the attributes that remain.\r\n */\r\nexport function sanitizeSvgMarkup(svg: string): string | null {\r\n if (typeof DOMParser === \"undefined\") {\r\n return null;\r\n }\r\n\r\n try {\r\n const doc = new DOMParser().parseFromString(svg, \"image/svg+xml\");\r\n const root = doc.documentElement;\r\n\r\n if (!root || root.tagName.toLowerCase() !== \"svg\" || doc.querySelector(\"parsererror\")) {\r\n return null;\r\n }\r\n\r\n if (!sanitizeElement(root)) {\r\n return null;\r\n }\r\n\r\n return new XMLSerializer().serializeToString(root);\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nexport function resolveIconMarkup(custom: string | undefined, fallback: string): string {\r\n if (!custom) {\r\n return fallback;\r\n }\r\n\r\n return sanitizeSvgMarkup(custom) ?? fallback;\r\n}\r\n","import type { MeasureIcons, MeasureStyleOptions } from \"./measure-type\";\r\nimport { resolveIconMarkup } from \"./svgSanitizer\";\r\n\r\nconst DEFAULT_TRASH_SVG = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M4 7h16M9 7V4h6v3M6 7l1 13h10l1-13\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>`;\r\nconst DEFAULT_CLOSE_SVG = `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M4 4l16 16M20 4L4 20\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\"/></svg>`;\r\nconst DEFAULT_CHECK_SVG = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M4 12l6 6 10-12\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>`;\r\n\r\ninterface MeasureBadgeCallbacks {\r\n onRemove: () => void;\r\n onClose: () => void;\r\n onCheck: () => void;\r\n}\r\n\r\nexport class MeasureBadge {\r\n private wrapper: HTMLDivElement;\r\n private valueEl: HTMLSpanElement;\r\n private trashButton: HTMLButtonElement;\r\n private closeButton: HTMLButtonElement;\r\n private checkButton: HTMLButtonElement;\r\n\r\n constructor(\r\n container: HTMLElement,\r\n style: MeasureStyleOptions,\r\n icons: MeasureIcons,\r\n callbacks: MeasureBadgeCallbacks,\r\n ) {\r\n this.wrapper = document.createElement(\"div\");\r\n this.valueEl = document.createElement(\"span\");\r\n this.trashButton = document.createElement(\"button\");\r\n this.closeButton = document.createElement(\"button\");\r\n this.checkButton = document.createElement(\"button\");\r\n\r\n this.applyWrapperStyles(style);\r\n this.applyValueStyles(style);\r\n this.applyButtonStyles(this.trashButton, style);\r\n this.applyButtonStyles(this.closeButton, style);\r\n this.applyButtonStyles(this.checkButton, style);\r\n\r\n this.trashButton.type = \"button\";\r\n this.closeButton.type = \"button\";\r\n this.checkButton.type = \"button\";\r\n this.trashButton.innerHTML = resolveIconMarkup(icons.trash, DEFAULT_TRASH_SVG);\r\n this.closeButton.innerHTML = resolveIconMarkup(icons.close, DEFAULT_CLOSE_SVG);\r\n this.checkButton.innerHTML = resolveIconMarkup(icons.check, DEFAULT_CHECK_SVG);\r\n\r\n const stop = (event: Event) => {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n };\r\n\r\n this.wrapper.addEventListener(\"mousedown\", stop);\r\n this.wrapper.addEventListener(\"dblclick\", stop);\r\n this.wrapper.addEventListener(\"contextmenu\", stop);\r\n this.trashButton.addEventListener(\"click\", (event) => {\r\n stop(event);\r\n callbacks.onRemove();\r\n });\r\n this.closeButton.addEventListener(\"click\", (event) => {\r\n stop(event);\r\n callbacks.onClose();\r\n });\r\n this.checkButton.addEventListener(\"click\", (event) => {\r\n stop(event);\r\n callbacks.onCheck();\r\n });\r\n\r\n this.wrapper.appendChild(this.valueEl);\r\n this.wrapper.appendChild(this.checkButton);\r\n this.wrapper.appendChild(this.trashButton);\r\n this.wrapper.appendChild(this.closeButton);\r\n this.wrapper.style.display = \"none\";\r\n container.appendChild(this.wrapper);\r\n }\r\n\r\n private applyWrapperStyles(style: MeasureStyleOptions) {\r\n const el = this.wrapper.style;\r\n el.position = \"absolute\";\r\n el.zIndex = \"5\";\r\n el.display = \"flex\";\r\n el.alignItems = \"center\";\r\n el.gap = style.badgeGap ?? \"8px\";\r\n el.padding = \"6px 8px\";\r\n el.background = style.badgeBackground ?? \"#FFFFFF\";\r\n el.borderRadius = style.badgeBorderRadius ?? \"12px\";\r\n el.boxShadow = style.badgeBoxShadow ?? \"0 2px 10px rgba(15, 23, 42, 0.18)\";\r\n el.border = style.badgeBorder ?? \"1px solid rgba(0,0,0,0.06)\";\r\n el.transform = \"translate(-50%, -140%)\";\r\n el.pointerEvents = \"auto\";\r\n el.userSelect = \"none\";\r\n el.whiteSpace = \"nowrap\";\r\n }\r\n\r\n private applyValueStyles(style: MeasureStyleOptions) {\r\n const el = this.valueEl.style;\r\n el.color = style.badgeTextColor ?? \"#19191A\";\r\n el.fontSize = style.badgeFontSize ?? \"14px\";\r\n el.fontWeight = style.badgeFontWeight ?? \"600\";\r\n el.lineHeight = \"18px\";\r\n }\r\n\r\n private applyButtonStyles(button: HTMLButtonElement, style: MeasureStyleOptions) {\r\n const el = button.style;\r\n const size = style.iconButtonSize ?? \"24px\";\r\n el.display = \"inline-flex\";\r\n el.alignItems = \"center\";\r\n el.justifyContent = \"center\";\r\n el.width = size;\r\n el.height = size;\r\n el.border = \"none\";\r\n el.background = \"transparent\";\r\n el.cursor = \"pointer\";\r\n el.color = style.badgeTextColor ?? \"#535969\";\r\n el.padding = \"0\";\r\n }\r\n\r\n setValue(text: string) {\r\n this.valueEl.textContent = text;\r\n }\r\n\r\n setCheckEnabled(enabled: boolean) {\r\n this.checkButton.style.opacity = enabled ? \"1\" : \"0.35\";\r\n this.checkButton.style.pointerEvents = enabled ? \"auto\" : \"none\";\r\n }\r\n\r\n setPosition(x: number, y: number) {\r\n this.wrapper.style.left = `${x}px`;\r\n this.wrapper.style.top = `${y}px`;\r\n }\r\n\r\n show() {\r\n this.wrapper.style.display = \"flex\";\r\n }\r\n\r\n hide() {\r\n this.wrapper.style.display = \"none\";\r\n }\r\n\r\n destroy() {\r\n this.wrapper.remove();\r\n }\r\n}\r\n\r\nexport class MeasureShapeBadge {\r\n private wrapper: HTMLDivElement;\r\n private valueEl: HTMLSpanElement;\r\n private trashButton: HTMLButtonElement;\r\n\r\n constructor(\r\n container: HTMLElement,\r\n style: MeasureStyleOptions,\r\n icons: MeasureIcons,\r\n onRemove: () => void,\r\n ) {\r\n this.wrapper = document.createElement(\"div\");\r\n this.valueEl = document.createElement(\"span\");\r\n this.trashButton = document.createElement(\"button\");\r\n\r\n const wrapperStyle = this.wrapper.style;\r\n wrapperStyle.position = \"absolute\";\r\n wrapperStyle.zIndex = \"4\";\r\n wrapperStyle.display = \"flex\";\r\n wrapperStyle.alignItems = \"center\";\r\n wrapperStyle.gap = style.badgeGap ?? \"6px\";\r\n wrapperStyle.padding = \"5px 7px\";\r\n wrapperStyle.background = style.badgeBackground ?? \"#FFFFFF\";\r\n wrapperStyle.borderRadius = style.badgeBorderRadius ?? \"12px\";\r\n wrapperStyle.boxShadow = style.badgeBoxShadow ?? \"0 2px 10px rgba(15, 23, 42, 0.18)\";\r\n wrapperStyle.border = style.badgeBorder ?? \"1px solid rgba(0,0,0,0.06)\";\r\n wrapperStyle.transform = \"translate(-50%, -50%)\";\r\n wrapperStyle.pointerEvents = \"auto\";\r\n wrapperStyle.userSelect = \"none\";\r\n wrapperStyle.whiteSpace = \"nowrap\";\r\n\r\n const valueStyle = this.valueEl.style;\r\n valueStyle.color = style.badgeTextColor ?? \"#19191A\";\r\n valueStyle.fontSize = style.badgeFontSize ?? \"13px\";\r\n valueStyle.fontWeight = style.badgeFontWeight ?? \"600\";\r\n valueStyle.lineHeight = \"16px\";\r\n\r\n const size = style.iconButtonSize ?? \"20px\";\r\n const buttonStyle = this.trashButton.style;\r\n buttonStyle.display = \"inline-flex\";\r\n buttonStyle.alignItems = \"center\";\r\n buttonStyle.justifyContent = \"center\";\r\n buttonStyle.width = size;\r\n buttonStyle.height = size;\r\n buttonStyle.border = \"none\";\r\n buttonStyle.background = \"transparent\";\r\n buttonStyle.cursor = \"pointer\";\r\n buttonStyle.color = style.badgeTextColor ?? \"#535969\";\r\n buttonStyle.padding = \"0\";\r\n\r\n this.trashButton.type = \"button\";\r\n this.trashButton.innerHTML = resolveIconMarkup(icons.trash, DEFAULT_TRASH_SVG);\r\n\r\n const stop = (event: Event) => {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n };\r\n\r\n this.wrapper.addEventListener(\"mousedown\", stop);\r\n this.wrapper.addEventListener(\"dblclick\", stop);\r\n this.wrapper.addEventListener(\"contextmenu\", stop);\r\n this.trashButton.addEventListener(\"click\", (event) => {\r\n stop(event);\r\n onRemove();\r\n });\r\n\r\n this.wrapper.appendChild(this.valueEl);\r\n this.wrapper.appendChild(this.trashButton);\r\n container.appendChild(this.wrapper);\r\n }\r\n\r\n setValue(text: string) {\r\n this.valueEl.textContent = text;\r\n }\r\n\r\n setPosition(x: number, y: number) {\r\n this.wrapper.style.left = `${x}px`;\r\n this.wrapper.style.top = `${y}px`;\r\n }\r\n\r\n destroy() {\r\n this.wrapper.remove();\r\n }\r\n}\r\n","import type {\r\n GeoJSONSource,\r\n Map as MapLibreMap,\r\n MapLayerMouseEvent,\r\n MapMouseEvent,\r\n} from \"maplibre-gl\";\r\n\r\nimport { lineLength, polygonArea, polygonCentroid, midpoint } from \"./geo\";\r\nimport { MeasureBadge, MeasureShapeBadge } from \"./badge\";\r\nimport type {\r\n GeoJsonFeature,\r\n GeoJsonFeatureCollection,\r\n GeoJsonLineStringGeometry,\r\n GeoJsonPointGeometry,\r\n GeoJsonPolygonGeometry,\r\n} from \"./geojson-type\";\r\nimport type {\r\n MeasureIcons,\r\n MeasureLabels,\r\n MeasureMode,\r\n MeasurePoint,\r\n MeasureShape,\r\n MeasureState,\r\n MeasureStyleOptions,\r\n MeasureToolOptions,\r\n} from \"./measure-type\";\r\n\r\nlet idCounter = 0;\r\nconst nextId = (prefix: string) => `${prefix}-${Date.now().toString(36)}-${(idCounter += 1)}`;\r\n\r\nlet instanceCounter = 0;\r\nconst nextDefaultPrefix = () => `mahal-measure-${(instanceCounter += 1)}`;\r\n\r\nconst DEFAULT_STYLE: Required<\r\n Pick<\r\n MeasureStyleOptions,\r\n | \"pointColor\"\r\n | \"pointStrokeColor\"\r\n | \"pointStrokeWidth\"\r\n | \"pointRadius\"\r\n | \"lineColor\"\r\n | \"lineWidth\"\r\n | \"fillColor\"\r\n | \"fillOpacity\"\r\n >\r\n> = {\r\n pointColor: \"#FFFFFF\",\r\n pointStrokeColor: \"#278960\",\r\n pointStrokeWidth: 2,\r\n pointRadius: 5,\r\n lineColor: \"#278960\",\r\n lineWidth: 3,\r\n fillColor: \"#278960\",\r\n fillOpacity: 0.15,\r\n};\r\n\r\nfunction formatDistance(meters: number, labels: MeasureLabels): string {\r\n if (meters >= 1000) {\r\n return `${(meters / 1000).toFixed(2)} ${labels.kilometers ?? \"км\"}`;\r\n }\r\n\r\n return `${Math.round(meters)} ${labels.meters ?? \"м\"}`;\r\n}\r\n\r\nfunction formatArea(squareMeters: number, labels: MeasureLabels): string {\r\n if (squareMeters >= 100000) {\r\n return `${(squareMeters / 1000000).toFixed(2)} ${labels.squareKilometers ?? \"км²\"}`;\r\n }\r\n\r\n return `${Math.round(squareMeters)} ${labels.squareMeters ?? \"м²\"}`;\r\n}\r\n\r\nfunction minShapePoints(mode: MeasureMode): number {\r\n return mode === \"area\" ? 3 : 2;\r\n}\r\n\r\nfunction emptyFeatureCollection<G>(): GeoJsonFeatureCollection<G> {\r\n return { type: \"FeatureCollection\", features: [] };\r\n}\r\n\r\nexport class MeasureTool {\r\n private map: MapLibreMap;\r\n private prefix: string;\r\n private style: MeasureStyleOptions;\r\n private labels: MeasureLabels;\r\n private originalCursor: string;\r\n private layerHandlersBound = false;\r\n\r\n private pointsSourceId: string;\r\n private linesSourceId: string;\r\n private fillsSourceId: string;\r\n private hoverPointSourceId: string;\r\n\r\n private pointsLayerId: string;\r\n private linesCasingLayerId: string;\r\n private linesLayerId: string;\r\n private fillsLayerId: string;\r\n private hoverPointLayerId: string;\r\n\r\n private mode: MeasureMode;\r\n private isActive = false;\r\n private draft: MeasureShape | null = null;\r\n private shapes: MeasureShape[] = [];\r\n\r\n private badge: MeasureBadge | null = null;\r\n private shapeBadges = new Map<string, MeasureShapeBadge>();\r\n private icons: MeasureIcons;\r\n private draggingPointId: string | null = null;\r\n private draggingShapeId: string | null = null;\r\n private dragPanWasEnabled = true;\r\n private suppressNextClick = false;\r\n private hoverInsert: { shapeId: string; index: number; lngLat: [number, number] } | null = null;\r\n\r\n private onChange?: (state: MeasureState) => void;\r\n private onCloseRequest?: () => void;\r\n\r\n private handleClick = (event: MapMouseEvent) => this.onMapClick(event);\r\n private handlePointMouseDown = (event: MapLayerMouseEvent) => this.onPointMouseDown(event);\r\n private handlePointMouseEnter = () => {\r\n if (!this.isActive) return;\r\n this.setCursor(\"pointer\");\r\n };\r\n private handlePointMouseLeave = () => {\r\n if (!this.isActive) return;\r\n this.setCursor(\"\");\r\n };\r\n private handlePointContextMenu = (event: MapLayerMouseEvent) => this.onPointContextMenu(event);\r\n private handleLineMouseMove = (event: MapLayerMouseEvent) => this.onLineMouseMove(event);\r\n private handleLineMouseLeave = () => this.clearHoverInsert();\r\n private handleLineMouseDown = (event: MapLayerMouseEvent) => this.onLineMouseDown(event);\r\n private handleStyleLoad = () => this.onStyleLoad();\r\n private handleViewportChange = () => {\r\n this.updateBadgePosition();\r\n this.updateShapeBadgePositions();\r\n };\r\n\r\n constructor(map: MapLibreMap, options: MeasureToolOptions = {}) {\r\n this.map = map;\r\n this.originalCursor = map.getCanvas().style.cursor;\r\n this.prefix = options.sourceIdPrefix ?? nextDefaultPrefix();\r\n this.style = options.style ?? {};\r\n this.labels = options.labels ?? {};\r\n this.icons = options.icons ?? {};\r\n this.mode = options.mode ?? \"distance\";\r\n this.onChange = options.onChange;\r\n this.onCloseRequest = options.onCloseRequest;\r\n\r\n this.pointsSourceId = `${this.prefix}-points`;\r\n this.linesSourceId = `${this.prefix}-lines`;\r\n this.fillsSourceId = `${this.prefix}-fills`;\r\n this.hoverPointSourceId = `${this.prefix}-hover-point`;\r\n\r\n this.pointsLayerId = `${this.prefix}-points-layer`;\r\n this.linesCasingLayerId = `${this.prefix}-lines-casing-layer`;\r\n this.linesLayerId = `${this.prefix}-lines-layer`;\r\n this.fillsLayerId = `${this.prefix}-fills-layer`;\r\n this.hoverPointLayerId = `${this.prefix}-hover-point-layer`;\r\n\r\n this.badge = new MeasureBadge(map.getContainer(), this.style, this.icons, {\r\n onRemove: () => this.removeShape((this.draft ?? this.getLastShape())?.id ?? \"\"),\r\n onClose: () => this.onCloseRequest?.(),\r\n onCheck: () => this.finishDraft(),\r\n });\r\n\r\n if (this.map.isStyleLoaded()) {\r\n this.ensureLayers();\r\n this.bindLayerHandlers();\r\n }\r\n\r\n this.map.on(\"click\", this.handleClick);\r\n this.map.on(\"style.load\", this.handleStyleLoad);\r\n this.map.on(\"move\", this.handleViewportChange);\r\n }\r\n\r\n // Delegated layer events (map.on(event, layerId, handler)) hit-test against\r\n // that layer internally before invoking our handler — MapLibre can throw if\r\n // the layer doesn't exist yet. Only bind them once the layer is actually\r\n // there, and never bind twice (style reloads must not duplicate handlers).\r\n private bindLayerHandlers() {\r\n if (this.layerHandlersBound) {\r\n return;\r\n }\r\n\r\n this.layerHandlersBound = true;\r\n\r\n this.map.on(\"mousedown\", this.pointsLayerId, this.handlePointMouseDown);\r\n this.map.on(\"mouseenter\", this.pointsLayerId, this.handlePointMouseEnter);\r\n this.map.on(\"mouseleave\", this.pointsLayerId, this.handlePointMouseLeave);\r\n this.map.on(\"contextmenu\", this.pointsLayerId, this.handlePointContextMenu);\r\n this.map.on(\"mousemove\", this.linesCasingLayerId, this.handleLineMouseMove);\r\n this.map.on(\"mouseleave\", this.linesCasingLayerId, this.handleLineMouseLeave);\r\n this.map.on(\"mousedown\", this.linesCasingLayerId, this.handleLineMouseDown);\r\n }\r\n\r\n private unbindLayerHandlers() {\r\n if (!this.layerHandlersBound) {\r\n return;\r\n }\r\n\r\n this.layerHandlersBound = false;\r\n\r\n this.map.off(\"mousedown\", this.pointsLayerId, this.handlePointMouseDown);\r\n this.map.off(\"mouseenter\", this.pointsLayerId, this.handlePointMouseEnter);\r\n this.map.off(\"mouseleave\", this.pointsLayerId, this.handlePointMouseLeave);\r\n this.map.off(\"contextmenu\", this.pointsLayerId, this.handlePointContextMenu);\r\n this.map.off(\"mousemove\", this.linesCasingLayerId, this.handleLineMouseMove);\r\n this.map.off(\"mouseleave\", this.linesCasingLayerId, this.handleLineMouseLeave);\r\n this.map.off(\"mousedown\", this.linesCasingLayerId, this.handleLineMouseDown);\r\n }\r\n\r\n start(mode: MeasureMode = this.mode) {\r\n this.isActive = true;\r\n\r\n const modeChanged = mode !== this.mode;\r\n this.setMode(mode);\r\n\r\n // setMode() already renders/emits when the mode actually changes. When it\r\n // doesn't (e.g. re-opening the tool in the same mode after stop()), it\r\n // no-ops, so we still need to render here to make a previously stopped\r\n // draft/badge visible again.\r\n if (!modeChanged) {\r\n this.render();\r\n this.emitChange();\r\n }\r\n }\r\n\r\n stop() {\r\n this.isActive = false;\r\n this.onPointDragUp();\r\n this.badge?.hide();\r\n this.clearHoverInsert();\r\n this.setCursor(this.originalCursor);\r\n this.emitChange();\r\n }\r\n\r\n setMode(mode: MeasureMode) {\r\n if (this.mode === mode) {\r\n return;\r\n }\r\n\r\n this.mode = mode;\r\n\r\n if (this.draft) {\r\n this.draft.mode = mode;\r\n this.recomputeShape(this.draft);\r\n }\r\n\r\n this.render();\r\n this.emitChange();\r\n }\r\n\r\n finishDraft() {\r\n this.commitOrDiscardDraft();\r\n this.render();\r\n this.emitChange();\r\n }\r\n\r\n removeShape(shapeId: string) {\r\n if (!shapeId) {\r\n return;\r\n }\r\n\r\n if (this.draft?.id === shapeId) {\r\n this.draft = null;\r\n } else {\r\n this.shapes = this.shapes.filter((shape) => shape.id !== shapeId);\r\n }\r\n\r\n if (this.hoverInsert?.shapeId === shapeId) {\r\n this.clearHoverInsert();\r\n }\r\n\r\n this.render();\r\n this.emitChange();\r\n }\r\n\r\n removePoint(shapeId: string, pointId: string) {\r\n const shape = this.findShape(shapeId);\r\n if (!shape) {\r\n return;\r\n }\r\n\r\n shape.points = shape.points.filter((point) => point.id !== pointId);\r\n\r\n if (shape.points.length === 0) {\r\n this.removeShape(shapeId);\r\n return;\r\n }\r\n\r\n // A draft is normally invalid while the user is still adding points — only\r\n // committed shapes must always satisfy minShapePoints().\r\n const isDraft = this.draft?.id === shapeId;\r\n\r\n if (!isDraft && shape.points.length < minShapePoints(shape.mode)) {\r\n this.removeShape(shapeId);\r\n return;\r\n }\r\n\r\n this.recomputeShape(shape);\r\n this.render();\r\n this.emitChange();\r\n }\r\n\r\n clearAll() {\r\n this.draft = null;\r\n this.shapes = [];\r\n this.clearHoverInsert();\r\n this.render();\r\n this.emitChange();\r\n }\r\n\r\n getState(): MeasureState {\r\n return {\r\n active: this.isActive,\r\n mode: this.mode,\r\n draft: this.draft ? this.cloneShape(this.draft) : null,\r\n shapes: this.shapes.map((shape) => this.cloneShape(shape)),\r\n };\r\n }\r\n\r\n destroy() {\r\n this.map.off(\"click\", this.handleClick);\r\n this.unbindLayerHandlers();\r\n this.map.off(\"style.load\", this.handleStyleLoad);\r\n this.map.off(\"move\", this.handleViewportChange);\r\n this.onPointDragUp();\r\n this.setCursor(this.originalCursor);\r\n this.badge?.destroy();\r\n this.badge = null;\r\n this.shapeBadges.forEach((shapeBadge) => shapeBadge.destroy());\r\n this.shapeBadges.clear();\r\n this.removeLayers();\r\n }\r\n\r\n private cloneShape(shape: MeasureShape): MeasureShape {\r\n return {\r\n ...shape,\r\n points: shape.points.map((point) => ({ ...point, lngLat: [...point.lngLat] as [number, number] })),\r\n };\r\n }\r\n\r\n private findShape(shapeId: string): MeasureShape | null {\r\n if (this.draft?.id === shapeId) {\r\n return this.draft;\r\n }\r\n\r\n return this.shapes.find((shape) => shape.id === shapeId) ?? null;\r\n }\r\n\r\n private getLastShape(): MeasureShape | null {\r\n return this.shapes[this.shapes.length - 1] ?? null;\r\n }\r\n\r\n private commitOrDiscardDraft() {\r\n if (!this.draft) {\r\n return;\r\n }\r\n\r\n if (this.draft.points.length >= minShapePoints(this.draft.mode)) {\r\n this.shapes.push(this.draft);\r\n }\r\n\r\n this.draft = null;\r\n }\r\n\r\n private ensureDraft(): MeasureShape {\r\n if (!this.draft) {\r\n this.draft = {\r\n id: nextId(\"measure-shape\"),\r\n mode: this.mode,\r\n points: [],\r\n closed: false,\r\n distance: 0,\r\n area: 0,\r\n };\r\n }\r\n\r\n return this.draft;\r\n }\r\n\r\n private recomputeShape(shape: MeasureShape) {\r\n const coordinates = shape.points.map((point) => point.lngLat);\r\n\r\n if (shape.mode === \"area\" && coordinates.length >= 3) {\r\n shape.closed = true;\r\n shape.area = polygonArea(coordinates);\r\n shape.distance = lineLength([...coordinates, coordinates[0] as [number, number]]);\r\n return;\r\n }\r\n\r\n shape.closed = false;\r\n shape.area = 0;\r\n shape.distance = lineLength(coordinates);\r\n }\r\n\r\n private onMapClick(event: MapMouseEvent) {\r\n if (!this.isActive) {\r\n return;\r\n }\r\n\r\n if (this.suppressNextClick) {\r\n this.suppressNextClick = false;\r\n return;\r\n }\r\n\r\n const hitFeatures = this.queryPointsLayer(event.point);\r\n\r\n if (hitFeatures.length > 0) {\r\n return;\r\n }\r\n\r\n const shape = this.ensureDraft();\r\n shape.points.push({\r\n id: nextId(\"measure-point\"),\r\n lngLat: [+event.lngLat.lng.toFixed(6), +event.lngLat.lat.toFixed(6)],\r\n });\r\n this.recomputeShape(shape);\r\n this.render();\r\n this.emitChange();\r\n }\r\n\r\n private onPointMouseDown(event: MapLayerMouseEvent) {\r\n if (!this.isActive) {\r\n return;\r\n }\r\n\r\n const feature = event.features?.[0];\r\n const shapeId = feature?.properties?.shapeId as string | undefined;\r\n const pointId = feature?.properties?.pointId as string | undefined;\r\n\r\n if (!shapeId || !pointId) {\r\n return;\r\n }\r\n\r\n event.preventDefault();\r\n this.beginPointDrag(shapeId, pointId);\r\n }\r\n\r\n private beginPointDrag(shapeId: string, pointId: string) {\r\n this.draggingShapeId = shapeId;\r\n this.draggingPointId = pointId;\r\n this.dragPanWasEnabled = this.map.dragPan.isEnabled();\r\n this.map.dragPan.disable();\r\n this.setCursor(\"grabbing\");\r\n\r\n this.map.on(\"mousemove\", this.onPointDragMove);\r\n this.map.on(\"mouseup\", this.onPointDragUp);\r\n window.addEventListener(\"mouseup\", this.onPointDragUp);\r\n }\r\n\r\n private onPointDragMove = (event: MapMouseEvent) => {\r\n if (!this.draggingShapeId || !this.draggingPointId) {\r\n return;\r\n }\r\n\r\n const shape = this.findShape(this.draggingShapeId);\r\n const point = shape?.points.find((item) => item.id === this.draggingPointId);\r\n\r\n if (!shape || !point) {\r\n return;\r\n }\r\n\r\n point.lngLat = [+event.lngLat.lng.toFixed(6), +event.lngLat.lat.toFixed(6)];\r\n this.recomputeShape(shape);\r\n this.render();\r\n this.emitChange();\r\n };\r\n\r\n private onPointDragUp = () => {\r\n if (!this.draggingPointId) {\r\n return;\r\n }\r\n\r\n this.stopDragListeners();\r\n\r\n if (this.dragPanWasEnabled) {\r\n this.map.dragPan.enable();\r\n }\r\n\r\n this.setCursor(\"pointer\");\r\n this.suppressNextClick = true;\r\n\r\n // MapLibre only fires \"click\" when pointer movement stayed under clickTolerance.\r\n // A real drag exceeds that, so no click ever arrives to consume the flag —\r\n // clear it after the current event loop cycle so it doesn't swallow the next\r\n // unrelated click.\r\n window.setTimeout(() => {\r\n this.suppressNextClick = false;\r\n }, 0);\r\n };\r\n\r\n private stopDragListeners() {\r\n this.map.off(\"mousemove\", this.onPointDragMove);\r\n this.map.off(\"mouseup\", this.onPointDragUp);\r\n window.removeEventListener(\"mouseup\", this.onPointDragUp);\r\n this.draggingShapeId = null;\r\n this.draggingPointId = null;\r\n }\r\n\r\n private projectPoint(lngLat: [number, number]): { x: number; y: number } {\r\n const projected = this.map.project(lngLat);\r\n return { x: projected.x, y: projected.y };\r\n }\r\n\r\n private closestPointOnSegment(\r\n p: { x: number; y: number },\r\n a: { x: number; y: number },\r\n b: { x: number; y: number },\r\n ): { x: number; y: number } {\r\n const abx = b.x - a.x;\r\n const aby = b.y - a.y;\r\n const lengthSquared = abx * abx + aby * aby;\r\n\r\n if (lengthSquared === 0) {\r\n return a;\r\n }\r\n\r\n const t = Math.max(\r\n 0,\r\n Math.min(1, ((p.x - a.x) * abx + (p.y - a.y) * aby) / lengthSquared),\r\n );\r\n\r\n return { x: a.x + abx * t, y: a.y + aby * t };\r\n }\r\n\r\n private findClosestPointOnShape(\r\n shape: MeasureShape,\r\n screenPoint: { x: number; y: number },\r\n ): { index: number; lngLat: [number, number] } | null {\r\n const projected = shape.points.map((point) => this.projectPoint(point.lngLat));\r\n const segmentCount = shape.closed ? projected.length : projected.length - 1;\r\n\r\n let bestIndex = -1;\r\n let bestScreen: { x: number; y: number } | null = null;\r\n let bestDistance = Infinity;\r\n\r\n for (let i = 0; i < segmentCount; i += 1) {\r\n const a = projected[i];\r\n const b = projected[(i + 1) % projected.length];\r\n\r\n if (!a || !b) {\r\n continue;\r\n }\r\n\r\n const candidate = this.closestPointOnSegment(screenPoint, a, b);\r\n const dx = candidate.x - screenPoint.x;\r\n const dy = candidate.y - screenPoint.y;\r\n const distance = Math.sqrt(dx * dx + dy * dy);\r\n\r\n if (distance < bestDistance) {\r\n bestDistance = distance;\r\n bestIndex = i;\r\n bestScreen = candidate;\r\n }\r\n }\r\n\r\n if (bestIndex === -1 || !bestScreen) {\r\n return null;\r\n }\r\n\r\n const lngLat = this.map.unproject([bestScreen.x, bestScreen.y]);\r\n\r\n return {\r\n index: bestIndex,\r\n lngLat: [+lngLat.lng.toFixed(6), +lngLat.lat.toFixed(6)],\r\n };\r\n }\r\n\r\n private queryPointsLayer(point: MapLayerMouseEvent[\"point\"] | MapMouseEvent[\"point\"]) {\r\n if (!this.map.getLayer(this.pointsLayerId)) {\r\n return [];\r\n }\r\n\r\n return this.map.queryRenderedFeatures(point, { layers: [this.pointsLayerId] });\r\n }\r\n\r\n private isOverExistingPoint(point: MapLayerMouseEvent[\"point\"]): boolean {\r\n return this.queryPointsLayer(point).length > 0;\r\n }\r\n\r\n private onLineMouseMove(event: MapLayerMouseEvent) {\r\n if (!this.isActive || this.draggingPointId || this.isOverExistingPoint(event.point)) {\r\n this.clearHoverInsert();\r\n return;\r\n }\r\n\r\n const feature = event.features?.[0];\r\n const shapeId = feature?.properties?.shapeId as string | undefined;\r\n const shape = shapeId ? this.findShape(shapeId) : null;\r\n\r\n if (!shapeId || !shape) {\r\n return;\r\n }\r\n\r\n const closest = this.findClosestPointOnShape(shape, event.point);\r\n\r\n if (!closest) {\r\n return;\r\n }\r\n\r\n this.hoverInsert = { shapeId, index: closest.index, lngLat: closest.lngLat };\r\n this.renderHoverPoint();\r\n this.setCursor(\"copy\");\r\n }\r\n\r\n private clearHoverInsert() {\r\n if (!this.hoverInsert) {\r\n return;\r\n }\r\n\r\n this.hoverInsert = null;\r\n this.renderHoverPoint();\r\n this.setCursor(\"\");\r\n }\r\n\r\n private onLineMouseDown(event: MapLayerMouseEvent) {\r\n if (!this.isActive || !this.hoverInsert) {\r\n return;\r\n }\r\n\r\n const feature = event.features?.[0];\r\n const shapeId = feature?.properties?.shapeId as string | undefined;\r\n\r\n if (!shapeId || shapeId !== this.hoverInsert.shapeId) {\r\n return;\r\n }\r\n\r\n const shape = this.findShape(shapeId);\r\n if (!shape) {\r\n return;\r\n }\r\n\r\n event.preventDefault();\r\n\r\n const newPoint: MeasurePoint = {\r\n id: nextId(\"measure-point\"),\r\n lngLat: this.hoverInsert.lngLat,\r\n };\r\n shape.points.splice(this.hoverInsert.index + 1, 0, newPoint);\r\n this.recomputeShape(shape);\r\n\r\n this.hoverInsert = null;\r\n this.renderHoverPoint();\r\n this.render();\r\n this.emitChange();\r\n\r\n this.beginPointDrag(shapeId, newPoint.id);\r\n }\r\n\r\n private renderHoverPoint() {\r\n const features: GeoJsonFeature<GeoJsonPointGeometry>[] = this.hoverInsert\r\n ? [\r\n {\r\n type: \"Feature\",\r\n properties: {},\r\n geometry: { type: \"Point\", coordinates: this.hoverInsert.lngLat },\r\n },\r\n ]\r\n : [];\r\n\r\n this.setSourceData(this.hoverPointSourceId, { type: \"FeatureCollection\", features });\r\n }\r\n\r\n private onPointContextMenu(event: MapLayerMouseEvent) {\r\n if (!this.isActive) {\r\n return;\r\n }\r\n\r\n const feature = event.features?.[0];\r\n const shapeId = feature?.properties?.shapeId as string | undefined;\r\n const pointId = feature?.properties?.pointId as string | undefined;\r\n\r\n if (!shapeId || !pointId) {\r\n return;\r\n }\r\n\r\n event.preventDefault();\r\n this.removePoint(shapeId, pointId);\r\n }\r\n\r\n private setCursor(cursor: string) {\r\n this.map.getCanvas().style.cursor = cursor;\r\n }\r\n\r\n private onStyleLoad() {\r\n this.ensureLayers();\r\n this.bindLayerHandlers();\r\n this.render();\r\n }\r\n\r\n private emitChange() {\r\n this.onChange?.(this.getState());\r\n }\r\n\r\n private ensureLayers() {\r\n const style = { ...DEFAULT_STYLE, ...this.style };\r\n\r\n if (!this.map.getSource(this.linesSourceId)) {\r\n this.map.addSource(this.linesSourceId, {\r\n type: \"geojson\",\r\n data: emptyFeatureCollection<GeoJsonLineStringGeometry>(),\r\n });\r\n }\r\n\r\n if (!this.map.getSource(this.fillsSourceId)) {\r\n this.map.addSource(this.fillsSourceId, {\r\n type: \"geojson\",\r\n data: emptyFeatureCollection<GeoJsonPolygonGeometry>(),\r\n });\r\n }\r\n\r\n if (!this.map.getSource(this.pointsSourceId)) {\r\n this.map.addSource(this.pointsSourceId, {\r\n type: \"geojson\",\r\n data: emptyFeatureCollection<GeoJsonPointGeometry>(),\r\n });\r\n }\r\n\r\n if (!this.map.getSource(this.hoverPointSourceId)) {\r\n this.map.addSource(this.hoverPointSourceId, {\r\n type: \"geojson\",\r\n data: emptyFeatureCollection<GeoJsonPointGeometry>(),\r\n });\r\n }\r\n\r\n if (!this.map.getLayer(this.fillsLayerId)) {\r\n this.map.addLayer({\r\n id: this.fillsLayerId,\r\n type: \"fill\",\r\n source: this.fillsSourceId,\r\n paint: {\r\n \"fill-color\": style.fillColor,\r\n \"fill-opacity\": style.fillOpacity,\r\n },\r\n });\r\n }\r\n\r\n if (!this.map.getLayer(this.linesCasingLayerId)) {\r\n this.map.addLayer({\r\n id: this.linesCasingLayerId,\r\n type: \"line\",\r\n source: this.linesSourceId,\r\n layout: { \"line-cap\": \"round\", \"line-join\": \"round\" },\r\n paint: {\r\n \"line-color\": \"#FFFFFF\",\r\n \"line-width\": style.lineWidth + 3,\r\n \"line-opacity\": 0.9,\r\n },\r\n });\r\n }\r\n\r\n if (!this.map.getLayer(this.linesLayerId)) {\r\n this.map.addLayer({\r\n id: this.linesLayerId,\r\n type: \"line\",\r\n source: this.linesSourceId,\r\n layout: { \"line-cap\": \"round\", \"line-join\": \"round\" },\r\n paint: {\r\n \"line-color\": style.lineColor,\r\n \"line-width\": style.lineWidth,\r\n ...(this.style.lineDasharray ? { \"line-dasharray\": this.style.lineDasharray } : {}),\r\n },\r\n });\r\n }\r\n\r\n if (!this.map.getLayer(this.hoverPointLayerId)) {\r\n this.map.addLayer({\r\n id: this.hoverPointLayerId,\r\n type: \"circle\",\r\n source: this.hoverPointSourceId,\r\n paint: {\r\n \"circle-radius\": Math.max(3, style.pointRadius - 1),\r\n \"circle-color\": style.pointColor,\r\n \"circle-stroke-color\": style.pointStrokeColor,\r\n \"circle-stroke-width\": style.pointStrokeWidth,\r\n \"circle-opacity\": 0.8,\r\n \"circle-stroke-opacity\": 0.8,\r\n },\r\n });\r\n }\r\n\r\n if (!this.map.getLayer(this.pointsLayerId)) {\r\n this.map.addLayer({\r\n id: this.pointsLayerId,\r\n type: \"circle\",\r\n source: this.pointsSourceId,\r\n paint: {\r\n \"circle-radius\": style.pointRadius,\r\n \"circle-color\": style.pointColor,\r\n \"circle-stroke-color\": style.pointStrokeColor,\r\n \"circle-stroke-width\": style.pointStrokeWidth,\r\n },\r\n });\r\n }\r\n\r\n }\r\n\r\n private removeLayers() {\r\n [\r\n this.pointsLayerId,\r\n this.hoverPointLayerId,\r\n this.linesLayerId,\r\n this.linesCasingLayerId,\r\n this.fillsLayerId,\r\n ].forEach((layerId) => {\r\n if (this.map.getLayer(layerId)) {\r\n this.map.removeLayer(layerId);\r\n }\r\n });\r\n\r\n [\r\n this.pointsSourceId,\r\n this.hoverPointSourceId,\r\n this.linesSourceId,\r\n this.fillsSourceId,\r\n ].forEach((sourceId) => {\r\n if (this.map.getSource(sourceId)) {\r\n this.map.removeSource(sourceId);\r\n }\r\n });\r\n }\r\n\r\n private setSourceData<G>(sourceId: string, data: GeoJsonFeatureCollection<G>) {\r\n const source = this.map.getSource(sourceId) as GeoJSONSource | undefined;\r\n source?.setData(data as never);\r\n }\r\n\r\n private buildLineFeature(shape: MeasureShape): GeoJsonFeature<GeoJsonLineStringGeometry> | null {\r\n if (shape.points.length < 2) {\r\n return null;\r\n }\r\n\r\n const coordinates = shape.points.map((point) => point.lngLat);\r\n\r\n return {\r\n type: \"Feature\",\r\n id: shape.id,\r\n properties: { shapeId: shape.id },\r\n geometry: {\r\n type: \"LineString\",\r\n coordinates: shape.closed ? [...coordinates, coordinates[0] as [number, number]] : coordinates,\r\n },\r\n };\r\n }\r\n\r\n private buildFillFeature(shape: MeasureShape): GeoJsonFeature<GeoJsonPolygonGeometry> | null {\r\n if (shape.mode !== \"area\" || shape.points.length < 3) {\r\n return null;\r\n }\r\n\r\n const coordinates = shape.points.map((point) => point.lngLat);\r\n\r\n return {\r\n type: \"Feature\",\r\n id: shape.id,\r\n properties: { shapeId: shape.id },\r\n geometry: {\r\n type: \"Polygon\",\r\n coordinates: [[...coordinates, coordinates[0] as [number, number]]],\r\n },\r\n };\r\n }\r\n\r\n private buildPointFeatures(shape: MeasureShape): GeoJsonFeature<GeoJsonPointGeometry>[] {\r\n return shape.points.map((point) => ({\r\n type: \"Feature\",\r\n id: point.id,\r\n properties: { shapeId: shape.id, pointId: point.id },\r\n geometry: { type: \"Point\", coordinates: point.lngLat },\r\n }));\r\n }\r\n\r\n private getShapeAnchor(shape: MeasureShape): [number, number] {\r\n const coordinates = shape.points.map((point) => point.lngLat);\r\n\r\n return shape.mode === \"area\" ? polygonCentroid(coordinates) : midpoint(coordinates);\r\n }\r\n\r\n private render() {\r\n const shapes = this.shapes;\r\n\r\n const lineFeatures = shapes\r\n .map((shape) => this.buildLineFeature(shape))\r\n .filter((feature): feature is GeoJsonFeature<GeoJsonLineStringGeometry> => Boolean(feature));\r\n const fillFeatures = shapes\r\n .map((shape) => this.buildFillFeature(shape))\r\n .filter((feature): feature is GeoJsonFeature<GeoJsonPolygonGeometry> => Boolean(feature));\r\n const pointFeatures = shapes.flatMap((shape) => this.buildPointFeatures(shape));\r\n\r\n if (this.draft) {\r\n const draftLine = this.buildLineFeature(this.draft);\r\n const draftFill = this.buildFillFeature(this.draft);\r\n\r\n if (draftLine) lineFeatures.push(draftLine);\r\n if (draftFill) fillFeatures.push(draftFill);\r\n pointFeatures.push(...this.buildPointFeatures(this.draft));\r\n }\r\n\r\n this.setSourceData(this.linesSourceId, { type: \"FeatureCollection\", features: lineFeatures });\r\n this.setSourceData(this.fillsSourceId, { type: \"FeatureCollection\", features: fillFeatures });\r\n this.setSourceData(this.pointsSourceId, { type: \"FeatureCollection\", features: pointFeatures });\r\n\r\n this.updateBadge();\r\n this.syncShapeBadges();\r\n }\r\n\r\n private syncShapeBadges() {\r\n const activeIds = new Set(this.shapes.map((shape) => shape.id));\r\n\r\n Array.from(this.shapeBadges.keys()).forEach((shapeId) => {\r\n if (!activeIds.has(shapeId)) {\r\n this.shapeBadges.get(shapeId)?.destroy();\r\n this.shapeBadges.delete(shapeId);\r\n }\r\n });\r\n\r\n this.shapes.forEach((shape) => {\r\n if (shape.points.length < minShapePoints(shape.mode)) {\r\n this.shapeBadges.get(shape.id)?.destroy();\r\n this.shapeBadges.delete(shape.id);\r\n return;\r\n }\r\n\r\n const value =\r\n shape.mode === \"area\" ? formatArea(shape.area, this.labels) : formatDistance(shape.distance, this.labels);\r\n\r\n let shapeBadge = this.shapeBadges.get(shape.id);\r\n if (!shapeBadge) {\r\n shapeBadge = new MeasureShapeBadge(this.map.getContainer(), this.style, this.icons, () =>\r\n this.removeShape(shape.id),\r\n );\r\n this.shapeBadges.set(shape.id, shapeBadge);\r\n }\r\n\r\n shapeBadge.setValue(value);\r\n const projected = this.map.project(this.getShapeAnchor(shape));\r\n shapeBadge.setPosition(projected.x, projected.y);\r\n });\r\n }\r\n\r\n private updateShapeBadgePositions() {\r\n this.shapes.forEach((shape) => {\r\n const shapeBadge = this.shapeBadges.get(shape.id);\r\n if (!shapeBadge) {\r\n return;\r\n }\r\n\r\n const projected = this.map.project(this.getShapeAnchor(shape));\r\n shapeBadge.setPosition(projected.x, projected.y);\r\n });\r\n }\r\n\r\n private updateBadge() {\r\n if (!this.badge) {\r\n return;\r\n }\r\n\r\n if (!this.isActive || !this.draft || this.draft.points.length === 0) {\r\n this.badge.hide();\r\n return;\r\n }\r\n\r\n const isValid = this.draft.points.length >= minShapePoints(this.draft.mode);\r\n const value =\r\n this.draft.mode === \"area\"\r\n ? formatArea(this.draft.area, this.labels)\r\n : formatDistance(this.draft.distance, this.labels);\r\n\r\n this.badge.setValue(isValid ? value : formatDistance(this.draft.distance, this.labels));\r\n this.badge.setCheckEnabled(isValid);\r\n this.badge.show();\r\n this.updateBadgePosition();\r\n }\r\n\r\n private updateBadgePosition() {\r\n if (!this.badge || !this.draft || this.draft.points.length === 0 || !this.isActive) {\r\n return;\r\n }\r\n\r\n const lastPoint = this.draft.points[this.draft.points.length - 1];\r\n if (!lastPoint) {\r\n return;\r\n }\r\n\r\n const projected = this.map.project(lastPoint.lngLat);\r\n this.badge.setPosition(projected.x, projected.y);\r\n }\r\n}\r\n"],"mappings":"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","names":["index_exports","__export","MahalMap","MahalMapDefaultMarker","MeasureTool","Router","Search","SearchByLocation","services_exports","measure_exports","utils_exports","__toCommonJS","CameraController","map","zoom","smooth","bearing","pitch","is3D","options","BASE_URL","LATLNGREGEX","LNGLATREGEX","DARK","LIGHT","VECTOR","GRAM_BASE","GRAM_PRESETS","buildGramStyleUrl","base","preset","appendQueryParam","styleUrl","name","value","separator","buildStyleUrl","lang","token","finalStyleUrl","apiKey","saveKey","param","clearKey","getApiKey","SVG_ROOT_PATTERN","SVG_MARKUP_PATTERN","updateSvgAttribute","svg","attribute","value","attributePattern","escapeSvgAttribute","createImageTag","url","normalizeInnerSvg","trimmedSvg","normalizedSvg","resolveInnerIcon","innerSvg","innerUrl","trimmedInnerSvg","trimmedInnerUrl","createDefaultMarkerSvg","color","innerIconOptions","MahalMapDefaultMarker","props","el","svg","createDefaultMarkerSvg","addMarker","maplibregl","map","marker","defaultStyles","DARK","LIGHT","logoColors","_MahalMap","GRAM_BASE","GRAM_PRESETS","options","lang","theme","buildStyleUrl","VECTOR","token","getApiKey","explicit","globalNs","maplibreObject","maps3dCtor","maplibre","language","engine","instance","instanceKey","enable3D","finalStyle","buildGramStyleUrl","transformRequest","defaultPitch","CameraController","cb","container","callback","check","marker","enabled","center","zoom","addMarker","map","layer","error","visible","layers","isMaps3DLayer","isBuildingLayer","logoHost","logoShadow","style","color","MahalMap","services_exports","__export","Router","Search","SearchByLocation","clearKey","getApiKey","saveKey","import_axios","api","axios","BASE_URL","routingApi","param","token","points","e","api","err","utils_exports","__export","checkCoordinates","debounce","geojsonPolyline","geometryPolyline_default","trimValue","checkCoordinates","coordinates","lat","lng","LATLNGREGEX","match","LNGLATREGEX","debounce","fn","delay","timer","args","resolve","result","geojsonPolyline","encoded","points","index","len","lat","lng","b","shift","result","dlat","dlng","geometryPolyline","coordinates","encoded","prevLat","prevLng","i","lng","lat","latE5","lngE5","dLat","dLng","encodeSignedNumber","num","sgnNum","encodeNumber","geometryPolyline_default","trimValue","value","cut","cleanValue","Router","param","typeData","token","res","routingApi","route","updated","r","geojsonPolyline","error","searchPost","params","api","error","searchByLocationPost","getSearch","param","token","additionalParam","searchData","searchPost","error","debouncedFn","debounce","Search","SearchByLocation","params","searchByLocationPost","measure_exports","__export","MeasureTool","haversineDistance","lineLength","midpoint","polygonArea","polygonCentroid","EARTH_RADIUS_M","toRadians","deg","normalizeLngDeltaDeg","deltaDeg","normalizeLngDeg","lngDeg","haversineDistance","a","b","lng1","lat1","lng2","lat2","phi1","phi2","deltaPhi","deltaLambda","sinDeltaPhi","sinDeltaLambda","centralAngleSegment","centralAngle","lineLength","points","total","i","polygonArea","p1","p2","vertexAverage","acc","point","polygonCentroid","referenceLng","unwrapped","lng","lat","signedAreaSum","cxSum","cySum","x0","y0","x1","y1","cross","signedArea","centroidLng","centroidLat","midpoint","segmentLengths","totalLength","length","targetLength","traversed","segmentLength","t","ALLOWED_TAGS","ALLOWED_ATTRS","URL_SENSITIVE_ATTRS","isSafeValue","attrName","value","normalized","sanitizeElement","element","attribute","name","child","sanitizeSvgMarkup","svg","doc","root","resolveIconMarkup","custom","fallback","DEFAULT_TRASH_SVG","DEFAULT_CLOSE_SVG","DEFAULT_CHECK_SVG","MeasureBadge","container","style","icons","callbacks","resolveIconMarkup","stop","event","el","button","size","text","enabled","x","y","MeasureShapeBadge","onRemove","wrapperStyle","valueStyle","buttonStyle","idCounter","nextId","prefix","instanceCounter","nextDefaultPrefix","DEFAULT_STYLE","formatDistance","meters","labels","formatArea","squareMeters","minShapePoints","mode","emptyFeatureCollection","MeasureTool","map","options","event","shape","point","item","MeasureBadge","modeChanged","shapeId","pointId","shapeBadge","coordinates","polygonArea","lineLength","feature","lngLat","projected","p","a","b","abx","aby","lengthSquared","t","screenPoint","segmentCount","bestIndex","bestScreen","bestDistance","i","candidate","dx","dy","distance","closest","newPoint","features","cursor","style","layerId","sourceId","data","polygonCentroid","midpoint","shapes","lineFeatures","fillFeatures","pointFeatures","draftLine","draftFill","activeIds","value","MeasureShapeBadge","isValid","lastPoint"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/core/CameraController.ts","../src/config/constants.ts","../src/services/authKey.ts","../src/markers/defaultMarkerSvg.ts","../src/markers/MahalMapDefaultMarker.ts","../src/markers/marker.adapter.ts","../src/core/MahalMap.ts","../src/services/index.ts","../src/services/httpClient.ts","../src/services/routing/routing.api.ts","../src/utils/index.ts","../src/utils/coordinates.ts","../src/utils/debounce.ts","../src/utils/polyline/geojsonPolyline.ts","../src/utils/polyline/geometryPolyline.ts","../src/utils/trimValue.ts","../src/services/routing/routing.service.ts","../src/services/search/search.api.ts","../src/services/search/search.service.ts","../src/measure/index.ts","../src/measure/geo.ts","../src/measure/svgSanitizer.ts","../src/measure/badge.ts","../src/measure/MeasureTool.ts"],"sourcesContent":["// Lib\r\nimport { MahalMap } from \"@core\";\r\nimport { Search, SearchByLocation, Router } from \"@services\";\r\nimport { MahalMapDefaultMarker } from \"@markers\";\r\nimport { MeasureTool } from \"@measure\";\r\n\r\n// utils\r\nimport * as keyUtils from \"@services\";\r\nimport * as utils from \"@utils\";\r\nimport * as measureUtils from \"@measure\";\r\n\r\nexport * from \"@sdk-types\";\r\nexport type {\r\n MeasureMode,\r\n MeasurePoint,\r\n MeasureShape,\r\n MeasureStyleOptions,\r\n MeasureIcons,\r\n MeasureLabels,\r\n MeasureToolOptions,\r\n MeasureState,\r\n} from \"@measure\";\r\n\r\nexport {\r\n MahalMap,\r\n Search,\r\n SearchByLocation,\r\n Router,\r\n keyUtils,\r\n MahalMapDefaultMarker,\r\n MeasureTool,\r\n measureUtils,\r\n utils,\r\n};\r\n","import type { Map, FlyToOptions } from \"maplibre-gl\";\r\n\r\nexport class CameraController {\r\n constructor(private map: Map) {}\r\n\r\n setZoom(zoom: number, smooth = true) {\r\n if (smooth) {\r\n this.map.easeTo({ zoom });\r\n } else {\r\n this.map.setZoom(zoom);\r\n }\r\n }\r\n\r\n setBearing(bearing: number, smooth = true) {\r\n smooth ? this.map.easeTo({ bearing }) : this.map.setBearing(bearing);\r\n }\r\n\r\n setPitch(pitch: number, smooth = true) {\r\n smooth ? this.map.easeTo({ pitch }) : this.map.setPitch(pitch);\r\n }\r\n\r\n toggle3D(is3D: boolean) {\r\n this.map.easeTo({\r\n pitch: is3D ? 60 : 0,\r\n bearing: is3D ? this.map.getBearing() : 0,\r\n duration: 800,\r\n });\r\n }\r\n\r\n resetNorth() {\r\n this.map.easeTo({\r\n bearing: 0,\r\n pitch: 0,\r\n duration: 600,\r\n });\r\n }\r\n\r\n flyTo(options: FlyToOptions) {\r\n this.map.flyTo({\r\n speed: 1.2,\r\n curve: 1.42,\r\n essential: true,\r\n ...options,\r\n });\r\n }\r\n\r\n getPitch() {\r\n return this.map.getPitch();\r\n }\r\n}\r\n","const BASE_URL = \"https://platform.mahal.tj/api/\";\r\nconst LATLNGREGEX =\r\n /^([-+]?(?:[1-8]?\\d(?:\\.\\d+)?|90(?:\\.0+)?)),\\s*([-+]?(?:180(?:\\.0+)?|(?:(?:1[0-7]\\d)|(?:[1-9]?\\d))(?:\\.\\d+)?))$/;\r\nconst LNGLATREGEX =\r\n /^([-+]?(?:180(?:\\.0+)?|(?:(?:1[0-7]\\d)|(?:[1-9]?\\d))(?:\\.\\d+)?)),\\s*([-+]?(?:[1-8]?\\d(?:\\.\\d+)?|90(?:\\.0+)?))$/;\r\n\r\nconst REGEX =\r\n /^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?),\\s*[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$/;\r\n\r\nconst DARK = \"https://mtile.gram.tj/custom-styles/dark-style.json\";\r\nconst LIGHT = \"https://mtile.gram.tj/custom-styles/mapstyle.json\";\r\nconst VECTOR =\r\n \"https://mtile.gram.tj/custom-styles/style_maptiler_basic_hn.json\";\r\n\r\nconst STYLE_LANG_PARAM = \"ru\";\r\n\r\nconst GRAM_BASE = \"https://navi.gram.tj\";\r\nconst GRAM_PRESETS = { light: \"road-urban-lab-v2\", dark: \"standard-night\" };\r\n\r\n// Пути платформы GramMaps, которым нужен ключ (?key=).\r\nconst GRAM_KEY_PATHS = [\r\n \"/maps\",\r\n \"/tiles\",\r\n \"/objects3d\",\r\n \"/traffic\",\r\n \"/data\",\r\n \"/key\",\r\n];\r\n\r\nfunction buildGramStyleUrl(base: string, preset: string) {\r\n return `${base}/maps/${preset}.json`;\r\n}\r\n\r\n/**\r\n * Запасной transformRequest для engine: \"3d\", когда Maps3D не подключен\r\n * (Maps3D.transformRequest недоступен): относительные пути уводит на base\r\n * и добавляет ?key=, иначе тайлы/стили уходят без ключа и получают 401.\r\n */\r\nfunction buildGramTransformRequest(base: string, apiKey?: string | null) {\r\n const normalizedBase = base.replace(/\\/+$/, \"\");\r\n\r\n return (url: string) => {\r\n if (!url) {\r\n return undefined;\r\n }\r\n\r\n const isRelative = url.startsWith(\"/\");\r\n const absoluteUrl = isRelative ? `${normalizedBase}${url}` : url;\r\n\r\n if (!absoluteUrl.startsWith(normalizedBase)) {\r\n return undefined;\r\n }\r\n\r\n const path = absoluteUrl.slice(normalizedBase.length).split(\"?\")[0];\r\n const needsKey = GRAM_KEY_PATHS.some(\r\n (keyPath) => path === keyPath || path.startsWith(`${keyPath}/`),\r\n );\r\n\r\n if (!needsKey || !apiKey || /[?&]key=/.test(absoluteUrl)) {\r\n return isRelative ? { url: absoluteUrl } : undefined;\r\n }\r\n\r\n return { url: appendQueryParam(absoluteUrl, \"key\", apiKey) };\r\n };\r\n}\r\n\r\nfunction appendQueryParam(styleUrl: string, name: string, value: string) {\r\n const separator = styleUrl.includes(\"?\") ? \"&\" : \"?\";\r\n return `${styleUrl}${separator}${name}=${encodeURIComponent(value)}`;\r\n}\r\n\r\nfunction buildStyleUrl(styleUrl: string, lang?: string, token?: string) {\r\n let finalStyleUrl = styleUrl;\r\n\r\n if (token) {\r\n finalStyleUrl = appendQueryParam(finalStyleUrl, \"token\", token);\r\n }\r\n\r\n if (lang === STYLE_LANG_PARAM) {\r\n finalStyleUrl = appendQueryParam(finalStyleUrl, \"lang\", STYLE_LANG_PARAM);\r\n }\r\n\r\n return finalStyleUrl;\r\n}\r\n\r\nexport {\r\n BASE_URL,\r\n LATLNGREGEX,\r\n LNGLATREGEX,\r\n REGEX,\r\n DARK,\r\n LIGHT,\r\n VECTOR,\r\n buildStyleUrl,\r\n GRAM_BASE,\r\n GRAM_PRESETS,\r\n buildGramStyleUrl,\r\n buildGramTransformRequest,\r\n};\r\n","let apiKey: string = \"\";\r\n\r\nfunction saveKey(param: string) {\r\n if (param === \"\") return;\r\n apiKey = param;\r\n}\r\n\r\nfunction clearKey() {\r\n apiKey = \"\";\r\n}\r\n\r\nconst getApiKey = () => apiKey;\r\n\r\nexport { saveKey, clearKey, getApiKey };\r\n","type DefaultMarkerInnerIconOptions = {\r\n innerSvg?: string;\r\n innerUrl?: string;\r\n};\r\n\r\nconst SVG_ROOT_PATTERN = /<svg[\\s>]/i;\r\nconst SVG_MARKUP_PATTERN =\r\n /<(svg|path|g|circle|rect|polygon|line|polyline|ellipse|use)\\b/i;\r\n\r\nconst updateSvgAttribute = (\r\n svg: string,\r\n attribute: string,\r\n value: string,\r\n): string => {\r\n const attributePattern = new RegExp(`\\\\s${attribute}=\"[^\"]*\"`, \"i\");\r\n\r\n if (attributePattern.test(svg)) {\r\n return svg.replace(attributePattern, ` ${attribute}=\"${value}\"`);\r\n }\r\n\r\n return svg.replace(/<svg\\b/i, `<svg ${attribute}=\"${value}\"`);\r\n};\r\n\r\nconst escapeSvgAttribute = (value: string): string =>\r\n value.replace(/&/g, \"&\").replace(/\"/g, \""\");\r\n\r\nconst createImageTag = (url: string): string =>\r\n `<image href=\"${escapeSvgAttribute(url)}\" x=\"14\" y=\"12\" width=\"22\" height=\"22\" style=\"filter: brightness(0) invert(1);\" />`;\r\n\r\nconst normalizeInnerSvg = (svg: string): string => {\r\n const trimmedSvg = svg.trim();\r\n\r\n if (SVG_ROOT_PATTERN.test(trimmedSvg)) {\r\n let normalizedSvg = updateSvgAttribute(trimmedSvg, \"x\", \"14\");\r\n normalizedSvg = updateSvgAttribute(normalizedSvg, \"y\", \"12\");\r\n normalizedSvg = updateSvgAttribute(normalizedSvg, \"width\", \"22\");\r\n normalizedSvg = updateSvgAttribute(normalizedSvg, \"height\", \"22\");\r\n\r\n if (!/\\spreserveAspectRatio=\"/i.test(normalizedSvg)) {\r\n normalizedSvg = normalizedSvg.replace(\r\n /<svg\\b/i,\r\n `<svg preserveAspectRatio=\"xMidYMid meet\"`,\r\n );\r\n }\r\n\r\n return normalizedSvg;\r\n }\r\n\r\n return `<g transform=\"translate(14 12)\">${trimmedSvg}</g>`;\r\n};\r\n\r\nconst resolveInnerIcon = ({\r\n innerSvg,\r\n innerUrl,\r\n}: DefaultMarkerInnerIconOptions): string => {\r\n const trimmedInnerSvg = innerSvg?.trim();\r\n const trimmedInnerUrl = innerUrl?.trim();\r\n\r\n if (trimmedInnerSvg) {\r\n if (SVG_MARKUP_PATTERN.test(trimmedInnerSvg)) {\r\n return normalizeInnerSvg(trimmedInnerSvg);\r\n }\r\n\r\n return createImageTag(trimmedInnerSvg);\r\n }\r\n\r\n if (trimmedInnerUrl) {\r\n return createImageTag(trimmedInnerUrl);\r\n }\r\n\r\n return \"\";\r\n};\r\n\r\nconst createDefaultMarkerSvg = (\r\n color: string,\r\n innerIconOptions: DefaultMarkerInnerIconOptions = {},\r\n) => `<svg\r\n width=\"50\"\r\n height=\"62\"\r\n viewBox=\"0 0 50 62\"\r\n fill=\"none\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n >\r\n <g filter=\"url(#filter0_d_367_31358)\">\r\n <path\r\n fill-rule=\"evenodd\"\r\n clip-rule=\"evenodd\"\r\n d=\"M25 2C36.598 2 46 11.402 46 23C46 33.1603 38.7844 41.6353 29.198 43.5803L25.6524 48.6575C25.5788 48.7633 25.4812 48.8497 25.3676 48.9093C25.254 48.9689 25.128 49 25 49C24.872 49 24.746 48.9689 24.6324 48.9093C24.5188 48.8497 24.4212 48.7633 24.3476 48.6575L20.802 43.5803C11.2156 41.6353 4 33.1603 4 23C4 11.402 13.402 2 25 2Z\"\r\n fill=\"${color ? color : \"#278960\"}\"\r\n />\r\n </g>\r\n <path\r\n d=\"M25 51C27.7614 51 30 53.2386 30 56C30 58.7614 27.7614 61 25 61C22.2386 61 20 58.7614 20 56C20 53.2386 22.2386 51 25 51Z\"\r\n fill=\"${color ? color : \"#278960\"}\"\r\n stroke=\"white\"\r\n stroke-width=\"2\"\r\n />\r\n <g clip-path=\"url(#clip0_367_31358)\">\r\n ${resolveInnerIcon(innerIconOptions)}\r\n </g>\r\n <defs>\r\n <filter\r\n id=\"filter0_d_367_31358\"\r\n x=\"0\"\r\n y=\"0\"\r\n width=\"50\"\r\n height=\"55\"\r\n filterUnits=\"userSpaceOnUse\"\r\n color-interpolation-filters=\"sRGB\"\r\n >\r\n <feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\" />\r\n <feColorMatrix\r\n in=\"SourceAlpha\"\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\r\n result=\"hardAlpha\"\r\n />\r\n <feOffset dy=\"2\" />\r\n <feGaussianBlur stdDeviation=\"2\" />\r\n <feComposite in2=\"hardAlpha\" operator=\"out\" />\r\n <feColorMatrix\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0.250234 0 0 0 0 0.660089 0 0 0 0 0.488619 0 0 0 0.24 0\"\r\n />\r\n <feBlend\r\n mode=\"normal\"\r\n in2=\"BackgroundImageFix\"\r\n result=\"effect1_dropShadow_367_31358\"\r\n />\r\n <feBlend\r\n mode=\"normal\"\r\n in=\"SourceGraphic\"\r\n in2=\"effect1_dropShadow_367_31358\"\r\n result=\"shape\"\r\n />\r\n </filter>\r\n <clipPath id=\"clip0_367_31358\">\r\n <rect\r\n width=\"22\"\r\n height=\"22\"\r\n fill=\"white\"\r\n transform=\"translate(14 12)\"\r\n />\r\n </clipPath>\r\n </defs>\r\n </svg>`;\r\n\r\nexport { createDefaultMarkerSvg };\r\n","import { createDefaultMarkerSvg } from \"./defaultMarkerSvg\";\r\nimport type { MahalMapDefaultMarkerProps } from \"@sdk-types\";\r\n\r\nclass MahalMapDefaultMarker {\r\n private element: HTMLElement;\r\n\r\n constructor(private props: MahalMapDefaultMarkerProps) {\r\n this.element = this.createElement();\r\n }\r\n\r\n private createElement(): HTMLElement {\r\n const el = document.createElement(\"div\");\r\n el.style.cursor = \"pointer\";\r\n\r\n const svg = this.props.svg\r\n ? this.applyColorToCustomSvg(this.props.svg)\r\n : createDefaultMarkerSvg(\r\n this.props.color ?? \"#278960\",\r\n {\r\n innerSvg: this.props.innerSvg,\r\n innerUrl: this.props.innerUrl,\r\n },\r\n );\r\n\r\n el.innerHTML = svg;\r\n\r\n if (this.props.draggable) {\r\n el.draggable = true;\r\n }\r\n\r\n return el;\r\n }\r\n\r\n private applyColorToCustomSvg(svg: string): string {\r\n if (!this.props.color) return svg;\r\n return svg.replace(/fill=\"[^\"]*\"/g, `fill=\"${this.props.color}\"`);\r\n }\r\n\r\n getElement() {\r\n return this.element;\r\n }\r\n\r\n getCoordinates() {\r\n return this.props.coordinates;\r\n }\r\n\r\n isDraggable() {\r\n return !!this.props.draggable;\r\n }\r\n\r\n getAnchor() {\r\n return this.props.anchor || \"center\";\r\n }\r\n}\r\n\r\nexport { MahalMapDefaultMarker };\r\n","import type { Map, Marker } from \"maplibre-gl\";\r\nimport type { IMapMarker } from \"@sdk-types\";\r\n\r\ntype MapLibreMarkerFactory = {\r\n Marker: new (...args: ConstructorParameters<typeof Marker>) => Marker;\r\n};\r\n\r\nexport function addMarker(\r\n maplibregl: MapLibreMarkerFactory,\r\n map: Map,\r\n marker: IMapMarker,\r\n) {\r\n const mapMarker = new maplibregl.Marker({\r\n element: marker.getElement(),\r\n draggable: marker.isDraggable?.() ?? false,\r\n anchor: marker.getAnchor?.() ?? \"center\",\r\n })\r\n .setLngLat(marker.getCoordinates())\r\n .addTo(map);\r\n\r\n return mapMarker;\r\n}\r\n","import type { Map as MapType, Marker } from \"maplibre-gl\";\r\nimport {\r\n DARK,\r\n LIGHT,\r\n VECTOR,\r\n buildStyleUrl,\r\n GRAM_BASE,\r\n GRAM_PRESETS,\r\n buildGramStyleUrl,\r\n buildGramTransformRequest,\r\n} from \"@config\";\r\nimport { CameraController } from \"./CameraController\";\r\n\r\nimport type {\r\n IMahalMapOptions,\r\n IMapMarker,\r\n MapEngine,\r\n MapLanguage,\r\n Maps3DCtor,\r\n IMaps3DLayer,\r\n Theme,\r\n} from \"@sdk-types\";\r\nimport { getApiKey } from \"@services/authKey\";\r\n\r\n// Adapter\r\nimport { addMarker } from \"@markers\";\r\n\r\nconst defaultStyles = { dark: DARK, light: LIGHT };\r\nconst logoColors = { dark: \"#ffffff\", light: \"#19191a\" };\r\n\r\ntype MapLibreApi = {\r\n Map: new (...args: ConstructorParameters<typeof MapType>) => MapType;\r\n Marker: new (...args: ConstructorParameters<typeof Marker>) => Marker;\r\n};\r\n\r\nexport class MahalMap {\r\n private static instances = new Map<string, MahalMap>();\r\n private static defaultLanguage: MapLanguage = \"tj\";\r\n\r\n private isReady = false;\r\n private readyCallbacks: Array<(map: MapType) => void> = [];\r\n\r\n private map!: MapType;\r\n private maplibre!: MapLibreApi;\r\n private camera!: CameraController;\r\n private logoHost?: HTMLDivElement;\r\n private logoShadow?: ShadowRoot;\r\n private logoObserver?: MutationObserver;\r\n\r\n private options!: IMahalMapOptions;\r\n private language: MapLanguage = \"tj\";\r\n private instanceKey = \"\";\r\n\r\n private engine: MapEngine = \"legacy\";\r\n private gramBase: string = GRAM_BASE;\r\n private gramPreset: string = GRAM_PRESETS.light;\r\n private presetIsExplicit = false;\r\n private maps3dCtor?: Maps3DCtor;\r\n private maps3dLayer?: IMaps3DLayer;\r\n private maps3dReady?: Promise<IMaps3DLayer | undefined>;\r\n private buildingsEnabled = false;\r\n\r\n private constructor() {}\r\n\r\n private static getInstanceKey(options: IMahalMapOptions) {\r\n return typeof options.container === \"string\" && options.container\r\n ? options.container\r\n : \"map\";\r\n }\r\n\r\n private static normalizeLanguage(lang?: string | null): MapLanguage {\r\n return lang === \"ru\" ? \"ru\" : \"tj\";\r\n }\r\n\r\n static setDefaultLanguage(lang?: string | null) {\r\n MahalMap.defaultLanguage = MahalMap.normalizeLanguage(lang);\r\n }\r\n\r\n private static getDefaultStyle(theme: Theme, lang: MapLanguage) {\r\n return buildStyleUrl(defaultStyles[theme], lang, MahalMap.getMapToken());\r\n }\r\n\r\n private static getVectorStyle() {\r\n return buildStyleUrl(VECTOR, undefined, MahalMap.getMapToken());\r\n }\r\n\r\n private static getMapToken() {\r\n const token = getApiKey();\r\n\r\n if (!token) {\r\n throw new Error(\r\n \"[MahalMap SDK] Map API key is required. Call keyUtils.saveKey() before creating the map or pass apikey in the SDK script URL.\",\r\n );\r\n }\r\n\r\n return token;\r\n }\r\n\r\n private static getMaps3DCtor(explicit?: Maps3DCtor): Maps3DCtor | undefined {\r\n if (explicit) {\r\n return explicit;\r\n }\r\n\r\n if (typeof window === \"undefined\") {\r\n return undefined;\r\n }\r\n\r\n // IIFE global build (maps3d.global.js, global-name=Maps3D) exposes a\r\n // namespace object { Maps3D: ctor }, not the constructor itself.\r\n const globalNs = (\r\n window as unknown as { Maps3D?: Maps3DCtor | { Maps3D?: Maps3DCtor } }\r\n ).Maps3D;\r\n\r\n if (typeof globalNs === \"function\") {\r\n return globalNs;\r\n }\r\n\r\n return globalNs?.Maps3D;\r\n }\r\n\r\n static create(\r\n options: IMahalMapOptions,\r\n maplibreObject?: MapLibreApi,\r\n maps3dCtor?: Maps3DCtor,\r\n ) {\r\n const globalMaplibre =\r\n typeof window !== \"undefined\"\r\n ? (window as unknown as { maplibregl?: MapLibreApi }).maplibregl\r\n : undefined;\r\n // Явно переданный инстанс важнее глобального: у страницы может быть свой\r\n // window.maplibregl другой версии, смешивать их нельзя.\r\n const maplibre = maplibreObject || globalMaplibre;\r\n\r\n if (!maplibre) {\r\n throw new Error(\r\n \"[MahalMap SDK] MapLibre GL was not found. Pass it as the second argument or include it through a script.\",\r\n );\r\n }\r\n\r\n const language = MahalMap.normalizeLanguage(\r\n options.lang || MahalMap.defaultLanguage,\r\n );\r\n const theme = options.theme === \"dark\" ? \"dark\" : \"light\";\r\n const engine: MapEngine = options.engine === \"3d\" ? \"3d\" : \"legacy\";\r\n\r\n const instance = new MahalMap();\r\n const instanceKey = MahalMap.getInstanceKey(options);\r\n\r\n instance.options = options;\r\n instance.language = language;\r\n instance.instanceKey = instanceKey;\r\n instance.maplibre = maplibre;\r\n instance.engine = engine;\r\n\r\n if (engine === \"3d\") {\r\n // 3D включен по умолчанию для engine:\"3d\", пока явно не выключен (enable3D: false).\r\n const enable3D = options.enable3D !== false;\r\n\r\n instance.buildingsEnabled = enable3D;\r\n instance.gramBase = options.base || GRAM_BASE;\r\n instance.presetIsExplicit = Boolean(options.preset);\r\n instance.gramPreset = options.preset || GRAM_PRESETS[theme];\r\n instance.maps3dCtor = MahalMap.getMaps3DCtor(maps3dCtor);\r\n\r\n const finalStyle = options.style\r\n ? options.style\r\n : buildGramStyleUrl(instance.gramBase, instance.gramPreset);\r\n\r\n // Без transformRequest запросы к платформе уходят без ?key= (401).\r\n // Если Maps3D не подключен, ставим собственный — он делает то же самое.\r\n const transformRequest = instance.maps3dCtor\r\n ? instance.maps3dCtor.transformRequest({\r\n base: instance.gramBase,\r\n apiKey: getApiKey() || undefined,\r\n })\r\n : buildGramTransformRequest(instance.gramBase, getApiKey());\r\n\r\n // Без наклона камеры (pitch) экструзия зданий не видна — вид строго сверху.\r\n const defaultPitch = enable3D ? 58 : 0;\r\n\r\n instance.map = new maplibre.Map({\r\n container: options.container || \"map\",\r\n style: finalStyle,\r\n center: options.center || [69.624024, 40.279687],\r\n zoom: options.zoom !== undefined ? options.zoom : 5,\r\n attributionControl: false,\r\n pitch: options.pitch !== undefined ? options.pitch : defaultPitch,\r\n ...(options.bearing !== undefined ? { bearing: options.bearing } : {}),\r\n ...(transformRequest ? { transformRequest } : {}),\r\n } as ConstructorParameters<typeof MapType>[0]);\r\n\r\n // Стили GramMaps несут свой fill-extrusion слой \"building-3d\" (плоские здания без окон).\r\n // Без скрытия он остаётся поверх/вместо процедурных Maps3D-зданий на каждой загрузке\r\n // стиля (в т.ч. после setStyle при смене темы) — визуально 3D не отличить от выключенного.\r\n // Хук нужен и при enable3D: false — иначе после toggle3DBuildings(true) смена темы\r\n // возвращает плоские здания поверх процедурных.\r\n instance.map.on(\"style.load\", () => {\r\n instance.setNativeBuildingsVisible(!instance.buildingsEnabled);\r\n });\r\n\r\n if (enable3D) {\r\n if (!instance.maps3dCtor) {\r\n throw new Error(\r\n \"[MahalMap SDK] Maps3D was not found. Pass it as the third argument to create() or include it through a script (window.Maps3D).\",\r\n );\r\n }\r\n\r\n instance.maps3dLayer = new instance.maps3dCtor({\r\n apiKey: getApiKey() || undefined,\r\n base: instance.gramBase,\r\n buildings: true,\r\n ...options.maps3d,\r\n });\r\n instance.attachMaps3DLayer(instance.maps3dLayer);\r\n }\r\n } else {\r\n const finalStyle = options.autoAddVectorSource\r\n ? MahalMap.getVectorStyle()\r\n : options.style\r\n ? options.style\r\n : MahalMap.getDefaultStyle(theme, language);\r\n\r\n instance.map = new maplibre.Map({\r\n container: options.container || \"map\",\r\n style: finalStyle as string,\r\n center: options.center || [69.624024, 40.279687],\r\n zoom: options.zoom !== undefined ? options.zoom : 5,\r\n attributionControl: false,\r\n ...(options.pitch !== undefined ? { pitch: options.pitch } : {}),\r\n ...(options.bearing !== undefined ? { bearing: options.bearing } : {}),\r\n });\r\n }\r\n\r\n instance.addLogo(theme);\r\n\r\n instance.map.on(\"load\", () => {\r\n instance.isReady = true;\r\n\r\n instance.camera = new CameraController(instance.map);\r\n\r\n instance.readyCallbacks.forEach((cb) => cb(instance.map));\r\n instance.readyCallbacks = [];\r\n });\r\n\r\n MahalMap.instances.set(instanceKey, instance);\r\n return instance;\r\n }\r\n\r\n static onReady(container: string, callback: (map: MapType) => void) {\r\n if (!MahalMap.instances.has(container)) {\r\n const check = setInterval(() => {\r\n if (MahalMap.instances.has(container)) {\r\n clearInterval(check);\r\n MahalMap.onReady(container, callback);\r\n }\r\n }, 50);\r\n return;\r\n }\r\n\r\n const instance = MahalMap.getInstance(container);\r\n\r\n if (instance.isReady) {\r\n callback(instance.map);\r\n } else {\r\n instance.readyCallbacks.push(callback);\r\n }\r\n }\r\n\r\n static getInstance(container: string): MahalMap {\r\n const instance = MahalMap.instances.get(container);\r\n\r\n if (!instance) {\r\n throw new Error(\"[MahalMap SDK] Map instance is not created\");\r\n }\r\n\r\n return instance;\r\n }\r\n\r\n static hasInstance(container: string): boolean {\r\n return MahalMap.instances.has(container);\r\n }\r\n\r\n static removeInstance(container: string): boolean {\r\n return MahalMap.instances.delete(container);\r\n }\r\n\r\n static addMarker(instance: MahalMap, marker: IMapMarker) {\r\n return instance.addMarker(marker);\r\n }\r\n\r\n static getCamera(instance: MahalMap) {\r\n return instance.getCamera();\r\n }\r\n\r\n static getMap(instance: MahalMap): MapType {\r\n return instance.getMap();\r\n }\r\n\r\n static setStyle(instance: MahalMap, theme: Theme) {\r\n instance.setStyle(theme);\r\n }\r\n\r\n static getMaps3DLayer(instance: MahalMap) {\r\n return instance.getMaps3DLayer();\r\n }\r\n\r\n static whenMaps3DReady(instance: MahalMap) {\r\n return instance.whenMaps3DReady();\r\n }\r\n\r\n static toggle3DBuildings(instance: MahalMap, enabled: boolean) {\r\n instance.toggle3DBuildings(enabled);\r\n }\r\n\r\n static setLanguage(instance: MahalMap, lang: MapLanguage) {\r\n instance.setLanguage(lang);\r\n }\r\n\r\n static setCenter(instance: MahalMap, center: [number, number]) {\r\n instance.setCenter(center);\r\n }\r\n\r\n static setZoom(instance: MahalMap, zoom: number) {\r\n instance.setZoom(zoom);\r\n }\r\n\r\n static destroy(instance: MahalMap) {\r\n instance.destroy();\r\n }\r\n\r\n addMarker(marker: IMapMarker) {\r\n return addMarker(this.maplibre, this.map, marker);\r\n }\r\n\r\n init(map: MapType) {\r\n this.map = map;\r\n this.camera = new CameraController(map);\r\n }\r\n\r\n getCamera() {\r\n return this.camera;\r\n }\r\n\r\n getMap(): MapType {\r\n return this.map;\r\n }\r\n\r\n setStyle(theme: Theme) {\r\n this.options.theme = theme;\r\n\r\n if (this.engine === \"3d\") {\r\n if (this.options.style || this.presetIsExplicit) {\r\n return;\r\n }\r\n\r\n this.gramPreset = GRAM_PRESETS[theme];\r\n this.map.setStyle(buildGramStyleUrl(this.gramBase, this.gramPreset));\r\n this.updateLogoColor(theme);\r\n return;\r\n }\r\n\r\n if (this.options.autoAddVectorSource) {\r\n return;\r\n }\r\n\r\n if (!this.options.style) {\r\n this.map.setStyle(MahalMap.getDefaultStyle(theme, this.language));\r\n }\r\n\r\n this.updateLogoColor(theme);\r\n }\r\n\r\n setLanguage(lang: MapLanguage) {\r\n this.language = MahalMap.normalizeLanguage(lang);\r\n this.options.lang = this.language;\r\n\r\n if (\r\n this.engine === \"3d\" ||\r\n this.options.autoAddVectorSource ||\r\n this.options.style\r\n ) {\r\n return;\r\n }\r\n\r\n const theme = this.options.theme === \"dark\" ? \"dark\" : \"light\";\r\n this.map.setStyle(MahalMap.getDefaultStyle(theme, this.language));\r\n }\r\n\r\n getMaps3DLayer(): IMaps3DLayer | undefined {\r\n return this.maps3dLayer;\r\n }\r\n\r\n /** Вкл/выкл детальные 3D-здания (Maps3D). Работает только для engine: \"3d\". */\r\n toggle3DBuildings(enabled: boolean) {\r\n if (this.engine !== \"3d\") {\r\n return;\r\n }\r\n\r\n this.buildingsEnabled = enabled;\r\n this.setNativeBuildingsVisible(!enabled);\r\n\r\n if (!this.maps3dLayer) {\r\n // Карта могла быть создана до подключения Maps3D (enable3D: false) — пробуем найти его сейчас.\r\n this.maps3dCtor = this.maps3dCtor || MahalMap.getMaps3DCtor();\r\n\r\n if (!enabled || !this.maps3dCtor) {\r\n return;\r\n }\r\n\r\n this.maps3dLayer = new this.maps3dCtor({\r\n apiKey: getApiKey() || undefined,\r\n base: this.gramBase,\r\n buildings: true,\r\n ...this.options.maps3d,\r\n });\r\n this.attachMaps3DLayer(this.maps3dLayer);\r\n return;\r\n }\r\n\r\n if (this.maps3dLayer.setBuildingsEnabled) {\r\n this.applyMaps3DBuildingMode(enabled);\r\n return;\r\n }\r\n\r\n if (!enabled) {\r\n this.maps3dLayer.destroy?.();\r\n this.maps3dLayer.remove?.();\r\n this.maps3dLayer = undefined;\r\n this.maps3dReady = undefined;\r\n }\r\n }\r\n\r\n /**\r\n * Промис готовности слоя Maps3D: резолвится после attach(), когда доступен layer.buildings.\r\n * Нужен для тонкой настройки окон/света — до attach контроллера зданий ещё нет.\r\n * Резолвится в undefined, если движок не \"3d\", слой выключен или attach упал.\r\n */\r\n whenMaps3DReady(): Promise<IMaps3DLayer | undefined> {\r\n return this.maps3dReady || Promise.resolve(undefined);\r\n }\r\n\r\n private attachMaps3DLayer(layer: IMaps3DLayer) {\r\n this.maps3dReady = Promise.resolve(layer.attach(this.map))\r\n .then(() => {\r\n if (this.maps3dLayer !== layer) {\r\n return undefined;\r\n }\r\n\r\n this.applyMaps3DBuildingMode(this.buildingsEnabled);\r\n return layer;\r\n })\r\n .catch((error: unknown) => {\r\n if (this.maps3dLayer === layer) {\r\n this.maps3dLayer = undefined;\r\n }\r\n\r\n this.buildingsEnabled = false;\r\n this.setNativeBuildingsVisible(true);\r\n console.error(\"[MahalMap SDK] Failed to attach Maps3D layer\", error);\r\n return undefined;\r\n });\r\n }\r\n\r\n private applyMaps3DBuildingMode(enabled: boolean) {\r\n if (!this.maps3dLayer) {\r\n return;\r\n }\r\n\r\n this.maps3dLayer.setBuildingsEnabled?.(enabled);\r\n this.maps3dLayer.buildings?.setWindows?.(enabled);\r\n }\r\n\r\n /**\r\n * Прячет/показывает нативные здания стиля GramMaps (\"building-3d\" и прочие\r\n * fill/fill-extrusion слои зданий), не задевая слои самого Maps3D. Нужно, иначе плоский слой\r\n * стиля рисуется поверх процедурных 3D-зданий и визуально их перекрывает.\r\n * Проверяем именно \"здание\" (id или source-layer), чтобы не гасить чужую экструзию\r\n * в пользовательском стиле.\r\n */\r\n private setNativeBuildingsVisible(visible: boolean) {\r\n const layers = this.map.getStyle()?.layers || [];\r\n\r\n for (const layer of layers) {\r\n const isMaps3DLayer = layer.id.startsWith(\"maps3d-\");\r\n const sourceLayer =\r\n \"source-layer\" in layer ? layer[\"source-layer\"] : undefined;\r\n const isBuildingLayer =\r\n (layer.type === \"fill-extrusion\" || layer.type === \"fill\") &&\r\n (sourceLayer === \"building\" ||\r\n layer.id.toLowerCase().includes(\"building\"));\r\n\r\n if (isMaps3DLayer || !isBuildingLayer) {\r\n continue;\r\n }\r\n\r\n try {\r\n this.map.setLayoutProperty(\r\n layer.id,\r\n \"visibility\",\r\n visible ? \"visible\" : \"none\",\r\n );\r\n } catch {\r\n // слой мог исчезнуть при смене стиля — не критично\r\n }\r\n }\r\n }\r\n\r\n setCenter(center: [number, number]) {\r\n this.map.setCenter(center);\r\n }\r\n\r\n setZoom(zoom: number) {\r\n this.map.setZoom(zoom);\r\n }\r\n\r\n destroy() {\r\n this.maps3dLayer?.destroy?.();\r\n this.maps3dLayer?.remove?.();\r\n this.maps3dLayer = undefined;\r\n this.maps3dReady = undefined;\r\n this.logoObserver?.disconnect();\r\n this.logoObserver = undefined;\r\n this.logoHost?.remove();\r\n this.logoHost = undefined;\r\n this.logoShadow = undefined;\r\n this.map.remove();\r\n MahalMap.instances.delete(this.instanceKey);\r\n }\r\n\r\n private addLogo(theme: \"dark\" | \"light\") {\r\n const container = this.map.getContainer();\r\n const logoHost = document.createElement(\"div\");\r\n const logoShadow = logoHost.attachShadow({ mode: \"closed\" });\r\n\r\n logoHost.setAttribute(\"aria-label\", \"Mahal\");\r\n logoHost.dataset.mahal = Math.random().toString(36).slice(2);\r\n this.logoHost = logoHost;\r\n this.logoShadow = logoShadow;\r\n\r\n this.applyLogoHostStyles();\r\n this.renderLogo(theme);\r\n container.appendChild(logoHost);\r\n this.observeLogo(container);\r\n }\r\n\r\n private updateLogoColor(theme: \"dark\" | \"light\") {\r\n if (!this.logoShadow) {\r\n return;\r\n }\r\n\r\n this.renderLogo(theme);\r\n }\r\n\r\n private renderLogo(theme: \"dark\" | \"light\") {\r\n if (!this.logoShadow) {\r\n return;\r\n }\r\n\r\n this.logoShadow.innerHTML = `\r\n <style>\r\n :host {\r\n all: initial;\r\n }\r\n\r\n .logo-wrap {\r\n display: block;\r\n width: 80px;\r\n height: 18.45px;\r\n line-height: 0;\r\n pointer-events: none;\r\n user-select: none;\r\n }\r\n\r\n svg {\r\n display: block;\r\n }\r\n </style>\r\n <span class=\"logo-wrap\" aria-hidden=\"true\">\r\n ${this.getLogoSvg(logoColors[theme])}\r\n </span>\r\n `;\r\n }\r\n\r\n private applyLogoHostStyles() {\r\n if (!this.logoHost) {\r\n return;\r\n }\r\n\r\n const style = this.logoHost.style;\r\n\r\n style.setProperty(\"position\", \"absolute\", \"important\");\r\n style.setProperty(\"right\", \"10px\", \"important\");\r\n style.setProperty(\"bottom\", \"10px\", \"important\");\r\n style.setProperty(\"z-index\", \"1\", \"important\");\r\n style.setProperty(\"display\", \"block\", \"important\");\r\n style.setProperty(\"visibility\", \"visible\", \"important\");\r\n style.setProperty(\"opacity\", \"1\", \"important\");\r\n style.setProperty(\"pointer-events\", \"none\", \"important\");\r\n style.setProperty(\"line-height\", \"0\", \"important\");\r\n style.setProperty(\"width\", \"80px\", \"important\");\r\n style.setProperty(\"height\", \"18.45px\", \"important\");\r\n }\r\n\r\n private observeLogo(container: HTMLElement) {\r\n if (!this.logoHost) {\r\n return;\r\n }\r\n\r\n this.logoObserver?.disconnect();\r\n this.logoObserver = new MutationObserver(() => {\r\n if (!this.logoHost) {\r\n return;\r\n }\r\n\r\n this.applyLogoHostStyles();\r\n\r\n if (!container.contains(this.logoHost)) {\r\n container.appendChild(this.logoHost);\r\n }\r\n });\r\n\r\n this.logoObserver.observe(container, { childList: true });\r\n this.logoObserver.observe(this.logoHost, {\r\n attributes: true,\r\n attributeFilter: [\"class\", \"style\", \"hidden\"],\r\n });\r\n }\r\n\r\n private getLogoSvg(color: string) {\r\n return `\r\n <svg class=\"logo\" width=\"80\" viewBox=\"0 0 143 33\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" style=\"opacity: 0.95;\">\r\n <g clip-path=\"url(#mahal-logo-text)\">\r\n <path d=\"M57.2317 27.0218H52.8158V17.4678C52.8522 16.33 52.5154 15.2116 51.8567 14.2832C51.5507 13.8592 51.1439 13.5179 50.6731 13.2903C50.2023 13.0627 49.6822 12.9558 49.1598 12.9793C48.6266 12.9617 48.0969 13.0725 47.6154 13.3022C47.1338 13.532 46.7145 13.874 46.3926 14.2995C45.6965 15.2066 45.3323 16.3248 45.3607 17.4678V27.0218H40.9472V9.14261H45.0371L45.3631 11.3142C45.7779 10.4819 46.4682 9.81897 47.3166 9.4381C48.1797 9.04305 49.1182 8.83982 50.0674 8.84243C52.6721 8.84243 54.4332 9.9525 55.3509 12.1726C56.7283 10.001 58.7194 8.91514 61.324 8.91514C63.8255 8.91514 65.7133 9.6445 66.9875 11.1032C68.2617 12.5618 68.8949 14.6553 68.8871 17.3834V27.0102H64.4688V17.3952C64.4688 16.1178 64.1913 15.0742 63.6363 14.2644C63.0813 13.4545 62.2371 13.0504 61.1036 13.052C60.5671 13.0338 60.0336 13.1404 59.5453 13.3634C59.0569 13.5864 58.6271 13.9197 58.2894 14.3371C57.5684 15.2182 57.1895 16.3298 57.2223 17.4678L57.2317 27.0218Z\" fill=\"${color}\" />\r\n <path d=\"M87.3807 11.6402L87.5261 9.18015H91.7614V27.0218H87.5988L87.3807 24.4164C86.851 25.4268 85.997 26.2296 84.9559 26.6959C83.911 27.2275 82.7623 27.5237 81.5906 27.5636C78.8656 27.587 76.6525 26.7725 74.9516 25.12C73.2506 23.4674 72.4001 21.1223 72.4001 18.0846C72.4001 15.1141 73.2748 12.8096 75.0243 11.1712C76.7737 9.5327 78.9992 8.72439 81.7008 8.74628C82.8702 8.73859 84.0244 9.01209 85.066 9.54366C86.0248 10.0029 86.8291 10.7314 87.3807 11.6402ZM82.0972 12.6908C81.4026 12.6688 80.7104 12.7854 80.0614 13.0339C79.4123 13.2823 78.8193 13.6575 78.3168 14.1377C77.3162 15.1008 76.8151 16.4156 76.8136 18.0822C76.812 19.7488 77.3131 21.0699 78.3168 22.0455C78.8166 22.5305 79.4089 22.9103 80.0583 23.162C80.7077 23.4138 81.401 23.5325 82.0972 23.5112C83.3119 23.549 84.4998 23.1505 85.446 22.3879C86.304 21.7164 86.8944 20.761 87.111 19.6933C87.3151 18.6471 87.3151 17.5713 87.111 16.525C86.8973 15.451 86.3068 14.4887 85.446 13.8118C84.4984 13.0487 83.3085 12.651 82.0925 12.6908H82.0972Z\" fill=\"${color}\" />\r\n <path d=\"M95.483 1.6875H99.8989V11.605C101.273 9.818 103.131 8.92531 105.471 8.92687C107.933 8.92687 109.767 9.69295 110.973 11.2251C112.178 12.7572 112.781 14.8858 112.781 17.6109V27.0218H108.367V17.6413C108.367 16.0779 107.999 14.914 107.263 14.1495C106.526 13.385 105.543 13.0042 104.313 13.0074C103.714 12.9928 103.119 13.1115 102.571 13.3548C102.024 13.5982 101.537 13.9601 101.147 14.4144C100.308 15.3743 99.862 16.6156 99.8989 17.8899V27.0101H95.483V1.6875Z\" fill=\"${color}\" />\r\n <path d=\"M130.515 11.6402L130.66 9.18015H134.893V27.0218H130.733L130.515 24.4164C129.984 25.4263 129.13 26.229 128.09 26.6959C127.045 27.2273 125.896 27.5235 124.724 27.5636C121.998 27.587 119.784 26.7725 118.083 25.12C116.382 23.4674 115.532 21.1223 115.532 18.0846C115.532 15.1141 116.406 12.8096 118.156 11.1712C119.905 9.5327 122.131 8.72439 124.832 8.74628C126.002 8.73804 127.156 9.01157 128.198 9.54366C129.157 10.0029 129.962 10.7313 130.515 11.6402ZM125.231 12.6908C124.536 12.6688 123.844 12.7853 123.194 13.0337C122.545 13.2822 121.951 13.6575 121.448 14.1377C120.446 15.1008 119.946 16.4156 119.947 18.0822C119.949 19.7488 120.449 21.0699 121.448 22.0455C121.949 22.5306 122.541 22.9103 123.191 23.1621C123.841 23.4139 124.534 23.5326 125.231 23.5112C126.445 23.5495 127.632 23.1509 128.577 22.3879C129.436 21.7171 130.027 20.7614 130.243 19.6933C130.447 18.6471 130.447 17.5713 130.243 16.525C130.03 15.4506 129.439 14.488 128.577 13.8118C127.632 13.0494 126.445 12.6516 125.231 12.6908Z\" fill=\"${color}\" />\r\n <path d=\"M138.622 1.72498H143V27.0218H138.622V1.72498Z\" fill=\"${color}\" />\r\n </g>\r\n <g clip-path=\"url(#mahal-logo-mark)\">\r\n <path d=\"M30.4142 14.0273H22.0831L27.974 8.1364C28.4165 7.69383 28.6651 7.09361 28.665 6.46779C28.6649 5.84197 28.4163 5.2418 27.9737 4.79932C27.5311 4.35684 26.9309 4.10829 26.3051 4.10835C25.6793 4.10841 25.0791 4.35708 24.6366 4.79965L18.7463 10.6906V2.35952C18.7463 1.73373 18.4978 1.13358 18.0553 0.691086C17.6128 0.248591 17.0126 0 16.3868 0C15.761 0 15.1609 0.248591 14.7184 0.691086C14.2759 1.13358 14.0273 1.73373 14.0273 2.35952V10.6906L8.13639 4.79965C7.69268 4.3631 7.09445 4.11958 6.472 4.12211C5.84955 4.12465 5.25332 4.37304 4.81318 4.81318C4.37304 5.25332 4.12465 5.84955 4.12211 6.472C4.11958 7.09445 4.3631 7.69268 4.79965 8.1364L10.6906 14.0273H2.35952C1.73373 14.0273 1.13358 14.2759 0.691084 14.7184C0.248589 15.1609 0 15.7611 0 16.3868C0 17.0126 0.248589 17.6128 0.691084 18.0553C1.13358 18.4978 1.73373 18.7464 2.35952 18.7464H10.6906L4.79965 24.6373C4.3631 25.081 4.11958 25.6792 4.12211 26.3017C4.12465 26.9241 4.37304 27.5203 4.81318 27.9605C5.25332 28.4006 5.84955 28.649 6.472 28.6516C7.09445 28.6541 7.69268 28.4106 8.13639 27.974L14.0273 22.0831V30.4142C14.0273 31.0399 14.2759 31.6401 14.7184 32.0826C15.1609 32.5251 15.761 32.7737 16.3868 32.7737C17.0126 32.7737 17.6128 32.5251 18.0553 32.0826C18.4978 31.6401 18.7463 31.0399 18.7463 30.4142V22.0831L24.6366 27.974C25.0791 28.4166 25.6793 28.6653 26.3051 28.6653C26.9309 28.6654 27.5311 28.4168 27.9737 27.9743C28.4163 27.5319 28.6649 26.9317 28.665 26.3059C28.6651 25.6801 28.4165 25.0798 27.974 24.6373L22.0831 18.7464H30.4142C31.0399 18.7464 31.6401 18.4978 32.0826 18.0553C32.5251 17.6128 32.7737 17.0126 32.7737 16.3868C32.7737 15.7611 32.5251 15.1609 32.0826 14.7184C31.6401 14.2759 31.0399 14.0273 30.4142 14.0273Z\" fill=\"#278960\" />\r\n </g>\r\n <defs>\r\n <clipPath id=\"mahal-logo-text\">\r\n <rect width=\"102.055\" height=\"25.8761\" fill=\"white\" transform=\"translate(40.9449 1.6875)\" />\r\n </clipPath>\r\n <clipPath id=\"mahal-logo-mark\">\r\n <rect width=\"32.7737\" height=\"32.7737\" fill=\"white\" />\r\n </clipPath>\r\n </defs>\r\n </svg>\r\n `;\r\n }\r\n}\r\n","export * from \"./authKey\";\nexport * from \"./routing\";\nexport * from \"./search\";\n","import axios from \"axios\";\r\nimport { BASE_URL } from \"@config\";\r\n\r\nexport const api = axios.create({\r\n baseURL: BASE_URL,\r\n});\r\n","import { api } from \"../httpClient\";\r\n\r\nconst routingApi = async (param: number[][], token: string) => {\r\n try {\r\n const points: { lng: number; lat: number }[] = [];\r\n\r\n param.forEach((e) => {\r\n points.push({ lng: e[0], lat: e[1] });\r\n });\r\n const response = await api.post(\"services/getRoutes\", {\r\n points,\r\n token,\r\n });\r\n return response.data;\r\n } catch (err) {\r\n console.error(err);\r\n throw err;\r\n }\r\n};\r\n\r\nexport { routingApi };\r\n","export * from \"./coordinates\";\r\nexport * from \"./debounce\";\r\nexport * from \"./polyline\";\r\nexport * from \"./trimValue\";\r\n","import { LATLNGREGEX, LNGLATREGEX } from \"@config\";\r\n\r\nexport function checkCoordinates(coordinates: string) {\r\n let lat, lng;\r\n if (LATLNGREGEX.test(coordinates)) {\r\n const match = coordinates.match(LATLNGREGEX);\r\n if (match) {\r\n [, lat, lng] = match; // Первый элемент — полное совпадение, пропускаем его\r\n }\r\n } else if (LNGLATREGEX.test(coordinates)) {\r\n const match = coordinates.match(LNGLATREGEX);\r\n if (match) {\r\n [, lng, lat] = match; // Меняем местами\r\n }\r\n } else {\r\n console.log(\"Неверный формат координат\");\r\n return null;\r\n }\r\n return { lat, lng };\r\n}\r\n","function debounce<F extends (...args: any[]) => Promise<any>>(\r\n fn: F,\r\n delay: number,\r\n) {\r\n let timer: ReturnType<typeof setTimeout>;\r\n\r\n return (...args: Parameters<F>): Promise<ReturnType<F>> => {\r\n if (timer) clearTimeout(timer);\r\n return new Promise((resolve) => {\r\n timer = setTimeout(async () => {\r\n const result = await fn(...args);\r\n resolve(result);\r\n }, delay);\r\n }) as Promise<ReturnType<F>>;\r\n };\r\n}\r\n\r\nexport { debounce };\r\n","function geojsonPolyline(encoded: string): number[][] {\r\n let points = [];\r\n let index = 0,\r\n len = encoded.length;\r\n let lat = 0,\r\n lng = 0;\r\n\r\n while (index < len) {\r\n let b,\r\n shift = 0,\r\n result = 0;\r\n do {\r\n b = encoded.charCodeAt(index++) - 63;\r\n result |= (b & 0x1f) << shift;\r\n shift += 5;\r\n } while (b >= 0x20);\r\n let dlat = result & 1 ? ~(result >> 1) : result >> 1;\r\n lat += dlat;\r\n\r\n shift = 0;\r\n result = 0;\r\n do {\r\n b = encoded.charCodeAt(index++) - 63;\r\n result |= (b & 0x1f) << shift;\r\n shift += 5;\r\n } while (b >= 0x20);\r\n let dlng = result & 1 ? ~(result >> 1) : result >> 1;\r\n lng += dlng;\r\n\r\n points.push([lng * 1e-5, lat * 1e-5]);\r\n }\r\n\r\n return points;\r\n}\r\n\r\nexport { geojsonPolyline };\r\n\r\n// Пример использования:\r\n\r\n// geojsonPolyline(\"yzocFzynhVq}@n}@o}@nzD\")\r\n\r\n// Вернёт массив вида [\r\n// [102.0, 0.5],\r\n// [103.0, 1.0],\r\n// [104.0, 0.5],\r\n// [105.0, 0.0]\r\n// ].\r\n","function geometryPolyline(coordinates: number[][]): string {\r\n let encoded = '';\r\n let prevLat = 0;\r\n let prevLng = 0;\r\n\r\n for (let i = 0; i < coordinates.length; i++) {\r\n const [lng, lat] = coordinates[i];\r\n \r\n // Умножаем координаты на 1e5 и округляем\r\n const latE5 = Math.round(lat * 1e5);\r\n const lngE5 = Math.round(lng * 1e5);\r\n\r\n // Вычисляем разницу от предыдущих значений\r\n const dLat = latE5 - prevLat;\r\n const dLng = lngE5 - prevLng;\r\n\r\n // Обновляем предыдущие значения\r\n prevLat = latE5;\r\n prevLng = lngE5;\r\n\r\n // Добавляем к закодированной строке\r\n encoded += encodeSignedNumber(dLat) + encodeSignedNumber(dLng);\r\n }\r\n\r\n return encoded;\r\n}\r\n\r\nfunction encodeSignedNumber(num: number) {\r\n let sgnNum = num << 1;\r\n if (num < 0) {\r\n sgnNum = ~sgnNum;\r\n }\r\n return encodeNumber(sgnNum);\r\n}\r\n\r\nfunction encodeNumber(num :number) {\r\n let encoded = '';\r\n while (num >= 0x20) {\r\n encoded += String.fromCharCode((0x20 | (num & 0x1f)) + 63);\r\n num >>= 5;\r\n }\r\n encoded += String.fromCharCode(num + 63);\r\n return encoded;\r\n}\r\n\r\nexport default geometryPolyline\r\n\r\n\r\n// Пример использования:\r\n\r\n// geometryPolyline([\r\n// [102.0, 0.5],\r\n// [103.0, 1.0],\r\n// [104.0, 0.5],\r\n// [105.0, 0.0]\r\n// ])\r\n\r\n// Вернёт строку вида \"yzocFzynhVq}@n}@o}@nzD\".","function trimValue(value: string, cut: number): string {\r\n if (cut <= 0) return \"\";\r\n\r\n // только обрезаем пробелы в начале и конце\r\n const cleanValue = value.trim();\r\n\r\n if (cut >= cleanValue.length) return cleanValue;\r\n\r\n return cleanValue.slice(0, cut);\r\n}\r\n\r\nexport { trimValue };\r\n","import { routingApi } from \"./routing.api\";\r\nimport { geojsonPolyline } from \"@utils\";\r\nimport type { IRoute } from \"@sdk-types\";\r\n\r\nasync function Router(\r\n param: number[][],\r\n typeData: string,\r\n token: string,\r\n): Promise<IRoute[]> {\r\n if (!token) {\r\n throw new Error(\"[MahalMap SDK] Router token is required\");\r\n }\r\n\r\n try {\r\n const res = await routingApi(param, token);\r\n\r\n if (!res?.data) return res;\r\n\r\n const data: IRoute[] = res.data;\r\n\r\n return data.map((route) => {\r\n const updated = { ...route };\r\n\r\n if (updated.route?.routes?.length) {\r\n updated.route.routes = updated.route.routes.map((r) => ({\r\n ...r,\r\n geometry:\r\n typeData === \"geojson\" && typeof r.geometry === \"string\"\r\n ? geojsonPolyline(r.geometry)\r\n : r.geometry,\r\n }));\r\n }\r\n\r\n return updated as IRoute;\r\n });\r\n } catch (error) {\r\n throw error;\r\n }\r\n}\r\n\r\nexport { Router };\r\n","import { api } from \"../httpClient\";\nimport type {\n ISearchByLocationParam,\n ISearchParam,\n ISearchResponse,\n IResponse,\n} from \"@sdk-types\";\n\nconst searchPost = async (params: ISearchParam) => {\n try {\n const response = await api.post<IResponse<ISearchResponse[]>>(\n \"services/getAddress\",\n null,\n {\n params,\n },\n );\n return response.data;\n } catch (error) {\n console.error(\"Error while searching address:\", error);\n throw error;\n }\n};\n\nconst searchByLocationPost = async (params: ISearchByLocationParam) => {\n try {\n const response = await api.post<IResponse<ISearchResponse[]>>(\n \"services/getAddressByLocation\",\n null,\n {\n params,\n },\n );\n return response.data;\n } catch (error) {\n console.error(\"Error while searching address by location:\", error);\n throw error;\n }\n};\n\nexport { searchPost, searchByLocationPost };\n","import { searchByLocationPost, searchPost } from \"./search.api\";\r\nimport {\r\n IAdditionalParamType,\r\n ISearchByLocationParam,\r\n ISearchParam,\r\n ISearchResponse,\r\n} from \"@sdk-types\";\r\nimport { debounce } from \"@utils\";\r\n// import { checkCoordinates } from \"@utils\";\r\n// import { REGEX } from \"@config\";\r\n\r\nasync function getSearch(\r\n param: string,\r\n token: string,\r\n additionalParam?: IAdditionalParamType,\r\n): Promise<ISearchResponse[]> {\r\n let searchData: ISearchParam = {\r\n text: param,\r\n token,\r\n ...additionalParam,\r\n };\r\n\r\n // if (param !== \"\") {\r\n // if (REGEX.test(param)) {\r\n // let coordinates = await checkCoordinates(param);\r\n // if (coordinates) {\r\n // searchData = {\r\n // lat: coordinates.lat ?? \"\",\r\n // lng: coordinates.lng ?? \"\",\r\n // };\r\n // }\r\n // } else {\r\n // searchData.text = param;\r\n // }\r\n // } else {\r\n // searchData.text = \"\";\r\n // }\r\n\r\n try {\r\n const res = await searchPost(searchData);\r\n return res.data;\r\n } catch (error) {\r\n throw error;\r\n }\r\n}\r\n\r\nconst debouncedFn = debounce(getSearch, 500);\r\n\r\nasync function Search(\r\n param: string,\r\n token: string,\r\n additionalParam?: IAdditionalParamType,\r\n): Promise<ISearchResponse[]> {\r\n if (!token) {\r\n throw new Error(\"[MahalMap SDK] Search token is required\");\r\n }\r\n\r\n return await debouncedFn(param, token, additionalParam);\r\n}\r\n\r\nasync function SearchByLocation(\r\n params: ISearchByLocationParam,\r\n): Promise<ISearchResponse> {\r\n if (!params.token) {\r\n throw new Error(\"[MahalMap SDK] SearchByLocation token is required\");\r\n }\r\n\r\n const searchData: ISearchByLocationParam = {\r\n ...params,\r\n };\r\n\r\n try {\r\n const res: any = await searchByLocationPost(searchData);\r\n return res;\r\n } catch (error) {\r\n throw error;\r\n }\r\n}\r\n\r\nexport { Search, SearchByLocation };\r\n","export * from \"./MeasureTool\";\r\nexport * from \"./geo\";\r\nexport * from \"./measure-type\";\r\n","const EARTH_RADIUS_M = 6371008.8;\r\n\r\nfunction toRadians(deg: number): number {\r\n return (deg * Math.PI) / 180;\r\n}\r\n\r\n/** Wraps a longitude delta (in degrees) into (-180, 180] so antimeridian crossings\r\n * (e.g. 179° -> -179°) are treated as a short ~2° step instead of a ~358° one. */\r\nfunction normalizeLngDeltaDeg(deltaDeg: number): number {\r\n return ((deltaDeg + 180) % 360 + 360) % 360 - 180;\r\n}\r\n\r\n/** Wraps a longitude (in degrees) into [-180, 180]. */\r\nfunction normalizeLngDeg(lngDeg: number): number {\r\n return ((lngDeg + 180) % 360 + 360) % 360 - 180;\r\n}\r\n\r\nexport function haversineDistance(\r\n a: [number, number],\r\n b: [number, number],\r\n): number {\r\n const [lng1, lat1] = a;\r\n const [lng2, lat2] = b;\r\n const phi1 = toRadians(lat1);\r\n const phi2 = toRadians(lat2);\r\n const deltaPhi = toRadians(lat2 - lat1);\r\n const deltaLambda = toRadians(lng2 - lng1);\r\n\r\n const sinDeltaPhi = Math.sin(deltaPhi / 2);\r\n const sinDeltaLambda = Math.sin(deltaLambda / 2);\r\n\r\n const centralAngleSegment =\r\n sinDeltaPhi * sinDeltaPhi +\r\n Math.cos(phi1) * Math.cos(phi2) * sinDeltaLambda * sinDeltaLambda;\r\n\r\n const centralAngle =\r\n 2 * Math.atan2(Math.sqrt(centralAngleSegment), Math.sqrt(1 - centralAngleSegment));\r\n\r\n return EARTH_RADIUS_M * centralAngle;\r\n}\r\n\r\nexport function lineLength(points: [number, number][]): number {\r\n let total = 0;\r\n\r\n for (let i = 1; i < points.length; i += 1) {\r\n total += haversineDistance(points[i - 1] as [number, number], points[i] as [number, number]);\r\n }\r\n\r\n return total;\r\n}\r\n\r\n/**\r\n * Spherical excess polygon area (same approach as Leaflet.GeometryUtil / turf's\r\n * geodesic area) — accurate enough for on-map measurement at city scale.\r\n */\r\nexport function polygonArea(points: [number, number][]): number {\r\n if (points.length < 3) {\r\n return 0;\r\n }\r\n\r\n let total = 0;\r\n\r\n for (let i = 0; i < points.length; i += 1) {\r\n const p1 = points[i] as [number, number];\r\n const p2 = points[(i + 1) % points.length] as [number, number];\r\n const deltaLambda = toRadians(normalizeLngDeltaDeg(p2[0] - p1[0]));\r\n const phi1 = toRadians(p1[1]);\r\n const phi2 = toRadians(p2[1]);\r\n\r\n total += deltaLambda * (2 + Math.sin(phi1) + Math.sin(phi2));\r\n }\r\n\r\n return Math.abs((total * EARTH_RADIUS_M * EARTH_RADIUS_M) / 2);\r\n}\r\n\r\nfunction vertexAverage(points: [number, number][]): [number, number] {\r\n const total = points.reduce(\r\n (acc, point) => [acc[0] + point[0], acc[1] + point[1]] as [number, number],\r\n [0, 0] as [number, number],\r\n );\r\n\r\n return [normalizeLngDeg(total[0] / points.length), total[1] / points.length];\r\n}\r\n\r\n/**\r\n * Area-weighted polygon centroid (shoelace-based), not a plain average of\r\n * vertices — a vertex average drifts outside the shape for concave or\r\n * unevenly-spaced polygons. Longitudes are unwrapped relative to the first\r\n * point first so shapes crossing the antimeridian don't collapse toward 0.\r\n */\r\nexport function polygonCentroid(points: [number, number][]): [number, number] {\r\n if (points.length === 0) {\r\n return [0, 0];\r\n }\r\n\r\n if (points.length < 3) {\r\n return vertexAverage(points);\r\n }\r\n\r\n const referenceLng = points[0]?.[0] ?? 0;\r\n const unwrapped = points.map(\r\n ([lng, lat]) => [referenceLng + normalizeLngDeltaDeg(lng - referenceLng), lat] as [number, number],\r\n );\r\n\r\n let signedAreaSum = 0;\r\n let cxSum = 0;\r\n let cySum = 0;\r\n\r\n for (let i = 0; i < unwrapped.length; i += 1) {\r\n const [x0, y0] = unwrapped[i] as [number, number];\r\n const [x1, y1] = unwrapped[(i + 1) % unwrapped.length] as [number, number];\r\n const cross = x0 * y1 - x1 * y0;\r\n\r\n signedAreaSum += cross;\r\n cxSum += (x0 + x1) * cross;\r\n cySum += (y0 + y1) * cross;\r\n }\r\n\r\n const signedArea = signedAreaSum / 2;\r\n\r\n // Degenerate polygon (collinear/duplicate points, zero area) — the shoelace\r\n // formula divides by zero here, fall back to a plain vertex average.\r\n if (Math.abs(signedArea) < 1e-12) {\r\n return vertexAverage(unwrapped);\r\n }\r\n\r\n const centroidLng = cxSum / (6 * signedArea);\r\n const centroidLat = cySum / (6 * signedArea);\r\n\r\n return [normalizeLngDeg(centroidLng), centroidLat];\r\n}\r\n\r\n/**\r\n * True midpoint along the line by cumulative length (not a vertex) — for an\r\n * uneven polyline the point at index Math.floor(n/2) can sit far from the\r\n * geometric middle. Longitude interpolation is antimeridian-aware.\r\n */\r\nexport function midpoint(points: [number, number][]): [number, number] {\r\n if (points.length === 0) {\r\n return [0, 0];\r\n }\r\n\r\n if (points.length === 1) {\r\n return points[0] as [number, number];\r\n }\r\n\r\n const segmentLengths: number[] = [];\r\n let totalLength = 0;\r\n\r\n for (let i = 1; i < points.length; i += 1) {\r\n const length = haversineDistance(points[i - 1] as [number, number], points[i] as [number, number]);\r\n segmentLengths.push(length);\r\n totalLength += length;\r\n }\r\n\r\n if (totalLength === 0) {\r\n return points[0] as [number, number];\r\n }\r\n\r\n const targetLength = totalLength / 2;\r\n let traversed = 0;\r\n\r\n for (let i = 1; i < points.length; i += 1) {\r\n const segmentLength = segmentLengths[i - 1] as number;\r\n\r\n if (traversed + segmentLength >= targetLength) {\r\n const t = segmentLength === 0 ? 0 : (targetLength - traversed) / segmentLength;\r\n const a = points[i - 1] as [number, number];\r\n const b = points[i] as [number, number];\r\n const lng = normalizeLngDeg(a[0] + normalizeLngDeltaDeg(b[0] - a[0]) * t);\r\n const lat = a[1] + (b[1] - a[1]) * t;\r\n\r\n return [lng, lat];\r\n }\r\n\r\n traversed += segmentLength;\r\n }\r\n\r\n return points[points.length - 1] as [number, number];\r\n}\r\n","// Strict allowlist: only static, non-referencing shape primitives are kept.\r\n// Anything capable of loading external resources, running script, or\r\n// animating (SMIL) is dropped by omission — this is a default-deny sanitizer,\r\n// not a denylist, so unknown/future attack surface is excluded by default.\r\nconst ALLOWED_TAGS = new Set([\r\n \"svg\",\r\n \"g\",\r\n \"path\",\r\n \"circle\",\r\n \"ellipse\",\r\n \"rect\",\r\n \"line\",\r\n \"polyline\",\r\n \"polygon\",\r\n]);\r\n\r\nconst ALLOWED_ATTRS = new Set([\r\n \"xmlns\",\r\n \"viewbox\",\r\n \"width\",\r\n \"height\",\r\n \"fill\",\r\n \"fill-rule\",\r\n \"fill-opacity\",\r\n \"stroke\",\r\n \"stroke-width\",\r\n \"stroke-linecap\",\r\n \"stroke-linejoin\",\r\n \"stroke-dasharray\",\r\n \"stroke-opacity\",\r\n \"opacity\",\r\n \"d\",\r\n \"cx\",\r\n \"cy\",\r\n \"r\",\r\n \"rx\",\r\n \"ry\",\r\n \"x\",\r\n \"y\",\r\n \"x1\",\r\n \"y1\",\r\n \"x2\",\r\n \"y2\",\r\n \"points\",\r\n \"transform\",\r\n]);\r\n\r\n// Presentation attributes that could otherwise carry a url(...) reference\r\n// (gradients/patterns/filters aren't in ALLOWED_TAGS, so any url() here is\r\n// either dead or an attempt to reach outside the document — reject either way).\r\nconst URL_SENSITIVE_ATTRS = new Set([\"fill\", \"stroke\"]);\r\n\r\nfunction isSafeValue(attrName: string, value: string): boolean {\r\n const normalized = value.trim().toLowerCase();\r\n\r\n if (normalized.includes(\"javascript:\") || normalized.includes(\"data:\") || normalized.includes(\"expression(\")) {\r\n return false;\r\n }\r\n\r\n if (URL_SENSITIVE_ATTRS.has(attrName) && normalized.includes(\"url(\")) {\r\n return false;\r\n }\r\n\r\n return true;\r\n}\r\n\r\nfunction sanitizeElement(element: Element): boolean {\r\n if (!ALLOWED_TAGS.has(element.tagName.toLowerCase())) {\r\n return false;\r\n }\r\n\r\n Array.from(element.attributes).forEach((attribute) => {\r\n const name = attribute.name.toLowerCase();\r\n\r\n if (!ALLOWED_ATTRS.has(name) || !isSafeValue(name, attribute.value)) {\r\n element.removeAttribute(attribute.name);\r\n }\r\n });\r\n\r\n Array.from(element.children).forEach((child) => {\r\n if (!sanitizeElement(child)) {\r\n child.remove();\r\n }\r\n });\r\n\r\n return true;\r\n}\r\n\r\n/**\r\n * Rebuilds an SVG icon from scratch using a strict tag/attribute allowlist\r\n * before it is inserted via innerHTML. Consumers may pass arbitrary icon\r\n * markup through MeasureIcons, so nothing outside static shape primitives\r\n * (path/circle/rect/line/polyline/polygon/g) survives — no <script>, <use>,\r\n * <image>, <a>, <style>, or SMIL (<animate>/<set>), and no url(...)/javascript:/\r\n * data: values on the attributes that remain.\r\n */\r\nexport function sanitizeSvgMarkup(svg: string): string | null {\r\n if (typeof DOMParser === \"undefined\") {\r\n return null;\r\n }\r\n\r\n try {\r\n const doc = new DOMParser().parseFromString(svg, \"image/svg+xml\");\r\n const root = doc.documentElement;\r\n\r\n if (!root || root.tagName.toLowerCase() !== \"svg\" || doc.querySelector(\"parsererror\")) {\r\n return null;\r\n }\r\n\r\n if (!sanitizeElement(root)) {\r\n return null;\r\n }\r\n\r\n return new XMLSerializer().serializeToString(root);\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nexport function resolveIconMarkup(custom: string | undefined, fallback: string): string {\r\n if (!custom) {\r\n return fallback;\r\n }\r\n\r\n return sanitizeSvgMarkup(custom) ?? fallback;\r\n}\r\n","import type { MeasureIcons, MeasureStyleOptions } from \"./measure-type\";\r\nimport { resolveIconMarkup } from \"./svgSanitizer\";\r\n\r\nconst DEFAULT_TRASH_SVG = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M4 7h16M9 7V4h6v3M6 7l1 13h10l1-13\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>`;\r\nconst DEFAULT_CLOSE_SVG = `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M4 4l16 16M20 4L4 20\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\"/></svg>`;\r\nconst DEFAULT_CHECK_SVG = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M4 12l6 6 10-12\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>`;\r\n\r\ninterface MeasureBadgeCallbacks {\r\n onRemove: () => void;\r\n onClose: () => void;\r\n onCheck: () => void;\r\n}\r\n\r\nexport class MeasureBadge {\r\n private wrapper: HTMLDivElement;\r\n private valueEl: HTMLSpanElement;\r\n private trashButton: HTMLButtonElement;\r\n private closeButton: HTMLButtonElement;\r\n private checkButton: HTMLButtonElement;\r\n\r\n constructor(\r\n container: HTMLElement,\r\n style: MeasureStyleOptions,\r\n icons: MeasureIcons,\r\n callbacks: MeasureBadgeCallbacks,\r\n ) {\r\n this.wrapper = document.createElement(\"div\");\r\n this.valueEl = document.createElement(\"span\");\r\n this.trashButton = document.createElement(\"button\");\r\n this.closeButton = document.createElement(\"button\");\r\n this.checkButton = document.createElement(\"button\");\r\n\r\n this.applyWrapperStyles(style);\r\n this.applyValueStyles(style);\r\n this.applyButtonStyles(this.trashButton, style);\r\n this.applyButtonStyles(this.closeButton, style);\r\n this.applyButtonStyles(this.checkButton, style);\r\n\r\n this.trashButton.type = \"button\";\r\n this.closeButton.type = \"button\";\r\n this.checkButton.type = \"button\";\r\n this.trashButton.innerHTML = resolveIconMarkup(icons.trash, DEFAULT_TRASH_SVG);\r\n this.closeButton.innerHTML = resolveIconMarkup(icons.close, DEFAULT_CLOSE_SVG);\r\n this.checkButton.innerHTML = resolveIconMarkup(icons.check, DEFAULT_CHECK_SVG);\r\n\r\n const stop = (event: Event) => {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n };\r\n\r\n this.wrapper.addEventListener(\"mousedown\", stop);\r\n this.wrapper.addEventListener(\"dblclick\", stop);\r\n this.wrapper.addEventListener(\"contextmenu\", stop);\r\n this.trashButton.addEventListener(\"click\", (event) => {\r\n stop(event);\r\n callbacks.onRemove();\r\n });\r\n this.closeButton.addEventListener(\"click\", (event) => {\r\n stop(event);\r\n callbacks.onClose();\r\n });\r\n this.checkButton.addEventListener(\"click\", (event) => {\r\n stop(event);\r\n callbacks.onCheck();\r\n });\r\n\r\n this.wrapper.appendChild(this.valueEl);\r\n this.wrapper.appendChild(this.checkButton);\r\n this.wrapper.appendChild(this.trashButton);\r\n this.wrapper.appendChild(this.closeButton);\r\n this.wrapper.style.display = \"none\";\r\n container.appendChild(this.wrapper);\r\n }\r\n\r\n private applyWrapperStyles(style: MeasureStyleOptions) {\r\n const el = this.wrapper.style;\r\n el.position = \"absolute\";\r\n el.zIndex = \"5\";\r\n el.display = \"flex\";\r\n el.alignItems = \"center\";\r\n el.gap = style.badgeGap ?? \"8px\";\r\n el.padding = \"6px 8px\";\r\n el.background = style.badgeBackground ?? \"#FFFFFF\";\r\n el.borderRadius = style.badgeBorderRadius ?? \"12px\";\r\n el.boxShadow = style.badgeBoxShadow ?? \"0 2px 10px rgba(15, 23, 42, 0.18)\";\r\n el.border = style.badgeBorder ?? \"1px solid rgba(0,0,0,0.06)\";\r\n el.transform = \"translate(-50%, -140%)\";\r\n el.pointerEvents = \"auto\";\r\n el.userSelect = \"none\";\r\n el.whiteSpace = \"nowrap\";\r\n }\r\n\r\n private applyValueStyles(style: MeasureStyleOptions) {\r\n const el = this.valueEl.style;\r\n el.color = style.badgeTextColor ?? \"#19191A\";\r\n el.fontSize = style.badgeFontSize ?? \"14px\";\r\n el.fontWeight = style.badgeFontWeight ?? \"600\";\r\n el.lineHeight = \"18px\";\r\n }\r\n\r\n private applyButtonStyles(button: HTMLButtonElement, style: MeasureStyleOptions) {\r\n const el = button.style;\r\n const size = style.iconButtonSize ?? \"24px\";\r\n el.display = \"inline-flex\";\r\n el.alignItems = \"center\";\r\n el.justifyContent = \"center\";\r\n el.width = size;\r\n el.height = size;\r\n el.border = \"none\";\r\n el.background = \"transparent\";\r\n el.cursor = \"pointer\";\r\n el.color = style.badgeTextColor ?? \"#535969\";\r\n el.padding = \"0\";\r\n }\r\n\r\n setValue(text: string) {\r\n this.valueEl.textContent = text;\r\n }\r\n\r\n setCheckEnabled(enabled: boolean) {\r\n this.checkButton.style.opacity = enabled ? \"1\" : \"0.35\";\r\n this.checkButton.style.pointerEvents = enabled ? \"auto\" : \"none\";\r\n }\r\n\r\n setPosition(x: number, y: number) {\r\n this.wrapper.style.left = `${x}px`;\r\n this.wrapper.style.top = `${y}px`;\r\n }\r\n\r\n show() {\r\n this.wrapper.style.display = \"flex\";\r\n }\r\n\r\n hide() {\r\n this.wrapper.style.display = \"none\";\r\n }\r\n\r\n destroy() {\r\n this.wrapper.remove();\r\n }\r\n}\r\n\r\nexport class MeasureShapeBadge {\r\n private wrapper: HTMLDivElement;\r\n private valueEl: HTMLSpanElement;\r\n private trashButton: HTMLButtonElement;\r\n\r\n constructor(\r\n container: HTMLElement,\r\n style: MeasureStyleOptions,\r\n icons: MeasureIcons,\r\n onRemove: () => void,\r\n ) {\r\n this.wrapper = document.createElement(\"div\");\r\n this.valueEl = document.createElement(\"span\");\r\n this.trashButton = document.createElement(\"button\");\r\n\r\n const wrapperStyle = this.wrapper.style;\r\n wrapperStyle.position = \"absolute\";\r\n wrapperStyle.zIndex = \"4\";\r\n wrapperStyle.display = \"flex\";\r\n wrapperStyle.alignItems = \"center\";\r\n wrapperStyle.gap = style.badgeGap ?? \"6px\";\r\n wrapperStyle.padding = \"5px 7px\";\r\n wrapperStyle.background = style.badgeBackground ?? \"#FFFFFF\";\r\n wrapperStyle.borderRadius = style.badgeBorderRadius ?? \"12px\";\r\n wrapperStyle.boxShadow = style.badgeBoxShadow ?? \"0 2px 10px rgba(15, 23, 42, 0.18)\";\r\n wrapperStyle.border = style.badgeBorder ?? \"1px solid rgba(0,0,0,0.06)\";\r\n wrapperStyle.transform = \"translate(-50%, -50%)\";\r\n wrapperStyle.pointerEvents = \"auto\";\r\n wrapperStyle.userSelect = \"none\";\r\n wrapperStyle.whiteSpace = \"nowrap\";\r\n\r\n const valueStyle = this.valueEl.style;\r\n valueStyle.color = style.badgeTextColor ?? \"#19191A\";\r\n valueStyle.fontSize = style.badgeFontSize ?? \"13px\";\r\n valueStyle.fontWeight = style.badgeFontWeight ?? \"600\";\r\n valueStyle.lineHeight = \"16px\";\r\n\r\n const size = style.iconButtonSize ?? \"20px\";\r\n const buttonStyle = this.trashButton.style;\r\n buttonStyle.display = \"inline-flex\";\r\n buttonStyle.alignItems = \"center\";\r\n buttonStyle.justifyContent = \"center\";\r\n buttonStyle.width = size;\r\n buttonStyle.height = size;\r\n buttonStyle.border = \"none\";\r\n buttonStyle.background = \"transparent\";\r\n buttonStyle.cursor = \"pointer\";\r\n buttonStyle.color = style.badgeTextColor ?? \"#535969\";\r\n buttonStyle.padding = \"0\";\r\n\r\n this.trashButton.type = \"button\";\r\n this.trashButton.innerHTML = resolveIconMarkup(icons.trash, DEFAULT_TRASH_SVG);\r\n\r\n const stop = (event: Event) => {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n };\r\n\r\n this.wrapper.addEventListener(\"mousedown\", stop);\r\n this.wrapper.addEventListener(\"dblclick\", stop);\r\n this.wrapper.addEventListener(\"contextmenu\", stop);\r\n this.trashButton.addEventListener(\"click\", (event) => {\r\n stop(event);\r\n onRemove();\r\n });\r\n\r\n this.wrapper.appendChild(this.valueEl);\r\n this.wrapper.appendChild(this.trashButton);\r\n container.appendChild(this.wrapper);\r\n }\r\n\r\n setValue(text: string) {\r\n this.valueEl.textContent = text;\r\n }\r\n\r\n setPosition(x: number, y: number) {\r\n this.wrapper.style.left = `${x}px`;\r\n this.wrapper.style.top = `${y}px`;\r\n }\r\n\r\n destroy() {\r\n this.wrapper.remove();\r\n }\r\n}\r\n","import type {\r\n GeoJSONSource,\r\n Map as MapLibreMap,\r\n MapLayerMouseEvent,\r\n MapMouseEvent,\r\n} from \"maplibre-gl\";\r\n\r\nimport { lineLength, polygonArea, polygonCentroid, midpoint } from \"./geo\";\r\nimport { MeasureBadge, MeasureShapeBadge } from \"./badge\";\r\nimport type {\r\n GeoJsonFeature,\r\n GeoJsonFeatureCollection,\r\n GeoJsonLineStringGeometry,\r\n GeoJsonPointGeometry,\r\n GeoJsonPolygonGeometry,\r\n} from \"./geojson-type\";\r\nimport type {\r\n MeasureIcons,\r\n MeasureLabels,\r\n MeasureMode,\r\n MeasurePoint,\r\n MeasureShape,\r\n MeasureState,\r\n MeasureStyleOptions,\r\n MeasureToolOptions,\r\n} from \"./measure-type\";\r\n\r\nlet idCounter = 0;\r\nconst nextId = (prefix: string) => `${prefix}-${Date.now().toString(36)}-${(idCounter += 1)}`;\r\n\r\nlet instanceCounter = 0;\r\nconst nextDefaultPrefix = () => `mahal-measure-${(instanceCounter += 1)}`;\r\n\r\nconst DEFAULT_STYLE: Required<\r\n Pick<\r\n MeasureStyleOptions,\r\n | \"pointColor\"\r\n | \"pointStrokeColor\"\r\n | \"pointStrokeWidth\"\r\n | \"pointRadius\"\r\n | \"lineColor\"\r\n | \"lineWidth\"\r\n | \"fillColor\"\r\n | \"fillOpacity\"\r\n >\r\n> = {\r\n pointColor: \"#FFFFFF\",\r\n pointStrokeColor: \"#278960\",\r\n pointStrokeWidth: 2,\r\n pointRadius: 5,\r\n lineColor: \"#278960\",\r\n lineWidth: 3,\r\n fillColor: \"#278960\",\r\n fillOpacity: 0.15,\r\n};\r\n\r\nfunction formatDistance(meters: number, labels: MeasureLabels): string {\r\n if (meters >= 1000) {\r\n return `${(meters / 1000).toFixed(2)} ${labels.kilometers ?? \"км\"}`;\r\n }\r\n\r\n return `${Math.round(meters)} ${labels.meters ?? \"м\"}`;\r\n}\r\n\r\nfunction formatArea(squareMeters: number, labels: MeasureLabels): string {\r\n if (squareMeters >= 100000) {\r\n return `${(squareMeters / 1000000).toFixed(2)} ${labels.squareKilometers ?? \"км²\"}`;\r\n }\r\n\r\n return `${Math.round(squareMeters)} ${labels.squareMeters ?? \"м²\"}`;\r\n}\r\n\r\nfunction minShapePoints(mode: MeasureMode): number {\r\n return mode === \"area\" ? 3 : 2;\r\n}\r\n\r\nfunction emptyFeatureCollection<G>(): GeoJsonFeatureCollection<G> {\r\n return { type: \"FeatureCollection\", features: [] };\r\n}\r\n\r\nexport class MeasureTool {\r\n private map: MapLibreMap;\r\n private prefix: string;\r\n private style: MeasureStyleOptions;\r\n private labels: MeasureLabels;\r\n private originalCursor: string;\r\n private layerHandlersBound = false;\r\n\r\n private pointsSourceId: string;\r\n private linesSourceId: string;\r\n private fillsSourceId: string;\r\n private hoverPointSourceId: string;\r\n\r\n private pointsLayerId: string;\r\n private linesCasingLayerId: string;\r\n private linesLayerId: string;\r\n private fillsLayerId: string;\r\n private hoverPointLayerId: string;\r\n\r\n private mode: MeasureMode;\r\n private isActive = false;\r\n private draft: MeasureShape | null = null;\r\n private shapes: MeasureShape[] = [];\r\n\r\n private badge: MeasureBadge | null = null;\r\n private shapeBadges = new Map<string, MeasureShapeBadge>();\r\n private icons: MeasureIcons;\r\n private draggingPointId: string | null = null;\r\n private draggingShapeId: string | null = null;\r\n private dragPanWasEnabled = true;\r\n private suppressNextClick = false;\r\n private hoverInsert: { shapeId: string; index: number; lngLat: [number, number] } | null = null;\r\n\r\n private onChange?: (state: MeasureState) => void;\r\n private onCloseRequest?: () => void;\r\n\r\n private handleClick = (event: MapMouseEvent) => this.onMapClick(event);\r\n private handlePointMouseDown = (event: MapLayerMouseEvent) => this.onPointMouseDown(event);\r\n private handlePointMouseEnter = () => {\r\n if (!this.isActive) return;\r\n this.setCursor(\"pointer\");\r\n };\r\n private handlePointMouseLeave = () => {\r\n if (!this.isActive) return;\r\n this.setCursor(\"\");\r\n };\r\n private handlePointContextMenu = (event: MapLayerMouseEvent) => this.onPointContextMenu(event);\r\n private handleLineMouseMove = (event: MapLayerMouseEvent) => this.onLineMouseMove(event);\r\n private handleLineMouseLeave = () => this.clearHoverInsert();\r\n private handleLineMouseDown = (event: MapLayerMouseEvent) => this.onLineMouseDown(event);\r\n private handleStyleLoad = () => this.onStyleLoad();\r\n private handleViewportChange = () => {\r\n this.updateBadgePosition();\r\n this.updateShapeBadgePositions();\r\n };\r\n\r\n constructor(map: MapLibreMap, options: MeasureToolOptions = {}) {\r\n this.map = map;\r\n this.originalCursor = map.getCanvas().style.cursor;\r\n this.prefix = options.sourceIdPrefix ?? nextDefaultPrefix();\r\n this.style = options.style ?? {};\r\n this.labels = options.labels ?? {};\r\n this.icons = options.icons ?? {};\r\n this.mode = options.mode ?? \"distance\";\r\n this.onChange = options.onChange;\r\n this.onCloseRequest = options.onCloseRequest;\r\n\r\n this.pointsSourceId = `${this.prefix}-points`;\r\n this.linesSourceId = `${this.prefix}-lines`;\r\n this.fillsSourceId = `${this.prefix}-fills`;\r\n this.hoverPointSourceId = `${this.prefix}-hover-point`;\r\n\r\n this.pointsLayerId = `${this.prefix}-points-layer`;\r\n this.linesCasingLayerId = `${this.prefix}-lines-casing-layer`;\r\n this.linesLayerId = `${this.prefix}-lines-layer`;\r\n this.fillsLayerId = `${this.prefix}-fills-layer`;\r\n this.hoverPointLayerId = `${this.prefix}-hover-point-layer`;\r\n\r\n this.badge = new MeasureBadge(map.getContainer(), this.style, this.icons, {\r\n onRemove: () => this.removeShape((this.draft ?? this.getLastShape())?.id ?? \"\"),\r\n onClose: () => this.onCloseRequest?.(),\r\n onCheck: () => this.finishDraft(),\r\n });\r\n\r\n if (this.map.isStyleLoaded()) {\r\n this.ensureLayers();\r\n this.bindLayerHandlers();\r\n }\r\n\r\n this.map.on(\"click\", this.handleClick);\r\n this.map.on(\"style.load\", this.handleStyleLoad);\r\n this.map.on(\"move\", this.handleViewportChange);\r\n }\r\n\r\n // Delegated layer events (map.on(event, layerId, handler)) hit-test against\r\n // that layer internally before invoking our handler — MapLibre can throw if\r\n // the layer doesn't exist yet. Only bind them once the layer is actually\r\n // there, and never bind twice (style reloads must not duplicate handlers).\r\n private bindLayerHandlers() {\r\n if (this.layerHandlersBound) {\r\n return;\r\n }\r\n\r\n this.layerHandlersBound = true;\r\n\r\n this.map.on(\"mousedown\", this.pointsLayerId, this.handlePointMouseDown);\r\n this.map.on(\"mouseenter\", this.pointsLayerId, this.handlePointMouseEnter);\r\n this.map.on(\"mouseleave\", this.pointsLayerId, this.handlePointMouseLeave);\r\n this.map.on(\"contextmenu\", this.pointsLayerId, this.handlePointContextMenu);\r\n this.map.on(\"mousemove\", this.linesCasingLayerId, this.handleLineMouseMove);\r\n this.map.on(\"mouseleave\", this.linesCasingLayerId, this.handleLineMouseLeave);\r\n this.map.on(\"mousedown\", this.linesCasingLayerId, this.handleLineMouseDown);\r\n }\r\n\r\n private unbindLayerHandlers() {\r\n if (!this.layerHandlersBound) {\r\n return;\r\n }\r\n\r\n this.layerHandlersBound = false;\r\n\r\n this.map.off(\"mousedown\", this.pointsLayerId, this.handlePointMouseDown);\r\n this.map.off(\"mouseenter\", this.pointsLayerId, this.handlePointMouseEnter);\r\n this.map.off(\"mouseleave\", this.pointsLayerId, this.handlePointMouseLeave);\r\n this.map.off(\"contextmenu\", this.pointsLayerId, this.handlePointContextMenu);\r\n this.map.off(\"mousemove\", this.linesCasingLayerId, this.handleLineMouseMove);\r\n this.map.off(\"mouseleave\", this.linesCasingLayerId, this.handleLineMouseLeave);\r\n this.map.off(\"mousedown\", this.linesCasingLayerId, this.handleLineMouseDown);\r\n }\r\n\r\n start(mode: MeasureMode = this.mode) {\r\n this.isActive = true;\r\n\r\n const modeChanged = mode !== this.mode;\r\n this.setMode(mode);\r\n\r\n // setMode() already renders/emits when the mode actually changes. When it\r\n // doesn't (e.g. re-opening the tool in the same mode after stop()), it\r\n // no-ops, so we still need to render here to make a previously stopped\r\n // draft/badge visible again.\r\n if (!modeChanged) {\r\n this.render();\r\n this.emitChange();\r\n }\r\n }\r\n\r\n stop() {\r\n this.isActive = false;\r\n this.onPointDragUp();\r\n this.badge?.hide();\r\n this.clearHoverInsert();\r\n this.setCursor(this.originalCursor);\r\n this.emitChange();\r\n }\r\n\r\n setMode(mode: MeasureMode) {\r\n if (this.mode === mode) {\r\n return;\r\n }\r\n\r\n this.mode = mode;\r\n\r\n if (this.draft) {\r\n this.draft.mode = mode;\r\n this.recomputeShape(this.draft);\r\n }\r\n\r\n this.render();\r\n this.emitChange();\r\n }\r\n\r\n finishDraft() {\r\n this.commitOrDiscardDraft();\r\n this.render();\r\n this.emitChange();\r\n }\r\n\r\n removeShape(shapeId: string) {\r\n if (!shapeId) {\r\n return;\r\n }\r\n\r\n if (this.draft?.id === shapeId) {\r\n this.draft = null;\r\n } else {\r\n this.shapes = this.shapes.filter((shape) => shape.id !== shapeId);\r\n }\r\n\r\n if (this.hoverInsert?.shapeId === shapeId) {\r\n this.clearHoverInsert();\r\n }\r\n\r\n this.render();\r\n this.emitChange();\r\n }\r\n\r\n removePoint(shapeId: string, pointId: string) {\r\n const shape = this.findShape(shapeId);\r\n if (!shape) {\r\n return;\r\n }\r\n\r\n shape.points = shape.points.filter((point) => point.id !== pointId);\r\n\r\n if (shape.points.length === 0) {\r\n this.removeShape(shapeId);\r\n return;\r\n }\r\n\r\n // A draft is normally invalid while the user is still adding points — only\r\n // committed shapes must always satisfy minShapePoints().\r\n const isDraft = this.draft?.id === shapeId;\r\n\r\n if (!isDraft && shape.points.length < minShapePoints(shape.mode)) {\r\n this.removeShape(shapeId);\r\n return;\r\n }\r\n\r\n this.recomputeShape(shape);\r\n this.render();\r\n this.emitChange();\r\n }\r\n\r\n clearAll() {\r\n this.draft = null;\r\n this.shapes = [];\r\n this.clearHoverInsert();\r\n this.render();\r\n this.emitChange();\r\n }\r\n\r\n getState(): MeasureState {\r\n return {\r\n active: this.isActive,\r\n mode: this.mode,\r\n draft: this.draft ? this.cloneShape(this.draft) : null,\r\n shapes: this.shapes.map((shape) => this.cloneShape(shape)),\r\n };\r\n }\r\n\r\n destroy() {\r\n this.map.off(\"click\", this.handleClick);\r\n this.unbindLayerHandlers();\r\n this.map.off(\"style.load\", this.handleStyleLoad);\r\n this.map.off(\"move\", this.handleViewportChange);\r\n this.onPointDragUp();\r\n this.setCursor(this.originalCursor);\r\n this.badge?.destroy();\r\n this.badge = null;\r\n this.shapeBadges.forEach((shapeBadge) => shapeBadge.destroy());\r\n this.shapeBadges.clear();\r\n this.removeLayers();\r\n }\r\n\r\n private cloneShape(shape: MeasureShape): MeasureShape {\r\n return {\r\n ...shape,\r\n points: shape.points.map((point) => ({ ...point, lngLat: [...point.lngLat] as [number, number] })),\r\n };\r\n }\r\n\r\n private findShape(shapeId: string): MeasureShape | null {\r\n if (this.draft?.id === shapeId) {\r\n return this.draft;\r\n }\r\n\r\n return this.shapes.find((shape) => shape.id === shapeId) ?? null;\r\n }\r\n\r\n private getLastShape(): MeasureShape | null {\r\n return this.shapes[this.shapes.length - 1] ?? null;\r\n }\r\n\r\n private commitOrDiscardDraft() {\r\n if (!this.draft) {\r\n return;\r\n }\r\n\r\n if (this.draft.points.length >= minShapePoints(this.draft.mode)) {\r\n this.shapes.push(this.draft);\r\n }\r\n\r\n this.draft = null;\r\n }\r\n\r\n private ensureDraft(): MeasureShape {\r\n if (!this.draft) {\r\n this.draft = {\r\n id: nextId(\"measure-shape\"),\r\n mode: this.mode,\r\n points: [],\r\n closed: false,\r\n distance: 0,\r\n area: 0,\r\n };\r\n }\r\n\r\n return this.draft;\r\n }\r\n\r\n private recomputeShape(shape: MeasureShape) {\r\n const coordinates = shape.points.map((point) => point.lngLat);\r\n\r\n if (shape.mode === \"area\" && coordinates.length >= 3) {\r\n shape.closed = true;\r\n shape.area = polygonArea(coordinates);\r\n shape.distance = lineLength([...coordinates, coordinates[0] as [number, number]]);\r\n return;\r\n }\r\n\r\n shape.closed = false;\r\n shape.area = 0;\r\n shape.distance = lineLength(coordinates);\r\n }\r\n\r\n private onMapClick(event: MapMouseEvent) {\r\n if (!this.isActive) {\r\n return;\r\n }\r\n\r\n if (this.suppressNextClick) {\r\n this.suppressNextClick = false;\r\n return;\r\n }\r\n\r\n const hitFeatures = this.queryPointsLayer(event.point);\r\n\r\n if (hitFeatures.length > 0) {\r\n return;\r\n }\r\n\r\n const shape = this.ensureDraft();\r\n shape.points.push({\r\n id: nextId(\"measure-point\"),\r\n lngLat: [+event.lngLat.lng.toFixed(6), +event.lngLat.lat.toFixed(6)],\r\n });\r\n this.recomputeShape(shape);\r\n this.render();\r\n this.emitChange();\r\n }\r\n\r\n private onPointMouseDown(event: MapLayerMouseEvent) {\r\n if (!this.isActive) {\r\n return;\r\n }\r\n\r\n const feature = event.features?.[0];\r\n const shapeId = feature?.properties?.shapeId as string | undefined;\r\n const pointId = feature?.properties?.pointId as string | undefined;\r\n\r\n if (!shapeId || !pointId) {\r\n return;\r\n }\r\n\r\n event.preventDefault();\r\n this.beginPointDrag(shapeId, pointId);\r\n }\r\n\r\n private beginPointDrag(shapeId: string, pointId: string) {\r\n this.draggingShapeId = shapeId;\r\n this.draggingPointId = pointId;\r\n this.dragPanWasEnabled = this.map.dragPan.isEnabled();\r\n this.map.dragPan.disable();\r\n this.setCursor(\"grabbing\");\r\n\r\n this.map.on(\"mousemove\", this.onPointDragMove);\r\n this.map.on(\"mouseup\", this.onPointDragUp);\r\n window.addEventListener(\"mouseup\", this.onPointDragUp);\r\n }\r\n\r\n private onPointDragMove = (event: MapMouseEvent) => {\r\n if (!this.draggingShapeId || !this.draggingPointId) {\r\n return;\r\n }\r\n\r\n const shape = this.findShape(this.draggingShapeId);\r\n const point = shape?.points.find((item) => item.id === this.draggingPointId);\r\n\r\n if (!shape || !point) {\r\n return;\r\n }\r\n\r\n point.lngLat = [+event.lngLat.lng.toFixed(6), +event.lngLat.lat.toFixed(6)];\r\n this.recomputeShape(shape);\r\n this.render();\r\n this.emitChange();\r\n };\r\n\r\n private onPointDragUp = () => {\r\n if (!this.draggingPointId) {\r\n return;\r\n }\r\n\r\n this.stopDragListeners();\r\n\r\n if (this.dragPanWasEnabled) {\r\n this.map.dragPan.enable();\r\n }\r\n\r\n this.setCursor(\"pointer\");\r\n this.suppressNextClick = true;\r\n\r\n // MapLibre only fires \"click\" when pointer movement stayed under clickTolerance.\r\n // A real drag exceeds that, so no click ever arrives to consume the flag —\r\n // clear it after the current event loop cycle so it doesn't swallow the next\r\n // unrelated click.\r\n window.setTimeout(() => {\r\n this.suppressNextClick = false;\r\n }, 0);\r\n };\r\n\r\n private stopDragListeners() {\r\n this.map.off(\"mousemove\", this.onPointDragMove);\r\n this.map.off(\"mouseup\", this.onPointDragUp);\r\n window.removeEventListener(\"mouseup\", this.onPointDragUp);\r\n this.draggingShapeId = null;\r\n this.draggingPointId = null;\r\n }\r\n\r\n private projectPoint(lngLat: [number, number]): { x: number; y: number } {\r\n const projected = this.map.project(lngLat);\r\n return { x: projected.x, y: projected.y };\r\n }\r\n\r\n private closestPointOnSegment(\r\n p: { x: number; y: number },\r\n a: { x: number; y: number },\r\n b: { x: number; y: number },\r\n ): { x: number; y: number } {\r\n const abx = b.x - a.x;\r\n const aby = b.y - a.y;\r\n const lengthSquared = abx * abx + aby * aby;\r\n\r\n if (lengthSquared === 0) {\r\n return a;\r\n }\r\n\r\n const t = Math.max(\r\n 0,\r\n Math.min(1, ((p.x - a.x) * abx + (p.y - a.y) * aby) / lengthSquared),\r\n );\r\n\r\n return { x: a.x + abx * t, y: a.y + aby * t };\r\n }\r\n\r\n private findClosestPointOnShape(\r\n shape: MeasureShape,\r\n screenPoint: { x: number; y: number },\r\n ): { index: number; lngLat: [number, number] } | null {\r\n const projected = shape.points.map((point) => this.projectPoint(point.lngLat));\r\n const segmentCount = shape.closed ? projected.length : projected.length - 1;\r\n\r\n let bestIndex = -1;\r\n let bestScreen: { x: number; y: number } | null = null;\r\n let bestDistance = Infinity;\r\n\r\n for (let i = 0; i < segmentCount; i += 1) {\r\n const a = projected[i];\r\n const b = projected[(i + 1) % projected.length];\r\n\r\n if (!a || !b) {\r\n continue;\r\n }\r\n\r\n const candidate = this.closestPointOnSegment(screenPoint, a, b);\r\n const dx = candidate.x - screenPoint.x;\r\n const dy = candidate.y - screenPoint.y;\r\n const distance = Math.sqrt(dx * dx + dy * dy);\r\n\r\n if (distance < bestDistance) {\r\n bestDistance = distance;\r\n bestIndex = i;\r\n bestScreen = candidate;\r\n }\r\n }\r\n\r\n if (bestIndex === -1 || !bestScreen) {\r\n return null;\r\n }\r\n\r\n const lngLat = this.map.unproject([bestScreen.x, bestScreen.y]);\r\n\r\n return {\r\n index: bestIndex,\r\n lngLat: [+lngLat.lng.toFixed(6), +lngLat.lat.toFixed(6)],\r\n };\r\n }\r\n\r\n private queryPointsLayer(point: MapLayerMouseEvent[\"point\"] | MapMouseEvent[\"point\"]) {\r\n if (!this.map.getLayer(this.pointsLayerId)) {\r\n return [];\r\n }\r\n\r\n return this.map.queryRenderedFeatures(point, { layers: [this.pointsLayerId] });\r\n }\r\n\r\n private isOverExistingPoint(point: MapLayerMouseEvent[\"point\"]): boolean {\r\n return this.queryPointsLayer(point).length > 0;\r\n }\r\n\r\n private onLineMouseMove(event: MapLayerMouseEvent) {\r\n if (!this.isActive || this.draggingPointId || this.isOverExistingPoint(event.point)) {\r\n this.clearHoverInsert();\r\n return;\r\n }\r\n\r\n const feature = event.features?.[0];\r\n const shapeId = feature?.properties?.shapeId as string | undefined;\r\n const shape = shapeId ? this.findShape(shapeId) : null;\r\n\r\n if (!shapeId || !shape) {\r\n return;\r\n }\r\n\r\n const closest = this.findClosestPointOnShape(shape, event.point);\r\n\r\n if (!closest) {\r\n return;\r\n }\r\n\r\n this.hoverInsert = { shapeId, index: closest.index, lngLat: closest.lngLat };\r\n this.renderHoverPoint();\r\n this.setCursor(\"copy\");\r\n }\r\n\r\n private clearHoverInsert() {\r\n if (!this.hoverInsert) {\r\n return;\r\n }\r\n\r\n this.hoverInsert = null;\r\n this.renderHoverPoint();\r\n this.setCursor(\"\");\r\n }\r\n\r\n private onLineMouseDown(event: MapLayerMouseEvent) {\r\n if (!this.isActive || !this.hoverInsert) {\r\n return;\r\n }\r\n\r\n const feature = event.features?.[0];\r\n const shapeId = feature?.properties?.shapeId as string | undefined;\r\n\r\n if (!shapeId || shapeId !== this.hoverInsert.shapeId) {\r\n return;\r\n }\r\n\r\n const shape = this.findShape(shapeId);\r\n if (!shape) {\r\n return;\r\n }\r\n\r\n event.preventDefault();\r\n\r\n const newPoint: MeasurePoint = {\r\n id: nextId(\"measure-point\"),\r\n lngLat: this.hoverInsert.lngLat,\r\n };\r\n shape.points.splice(this.hoverInsert.index + 1, 0, newPoint);\r\n this.recomputeShape(shape);\r\n\r\n this.hoverInsert = null;\r\n this.renderHoverPoint();\r\n this.render();\r\n this.emitChange();\r\n\r\n this.beginPointDrag(shapeId, newPoint.id);\r\n }\r\n\r\n private renderHoverPoint() {\r\n const features: GeoJsonFeature<GeoJsonPointGeometry>[] = this.hoverInsert\r\n ? [\r\n {\r\n type: \"Feature\",\r\n properties: {},\r\n geometry: { type: \"Point\", coordinates: this.hoverInsert.lngLat },\r\n },\r\n ]\r\n : [];\r\n\r\n this.setSourceData(this.hoverPointSourceId, { type: \"FeatureCollection\", features });\r\n }\r\n\r\n private onPointContextMenu(event: MapLayerMouseEvent) {\r\n if (!this.isActive) {\r\n return;\r\n }\r\n\r\n const feature = event.features?.[0];\r\n const shapeId = feature?.properties?.shapeId as string | undefined;\r\n const pointId = feature?.properties?.pointId as string | undefined;\r\n\r\n if (!shapeId || !pointId) {\r\n return;\r\n }\r\n\r\n event.preventDefault();\r\n this.removePoint(shapeId, pointId);\r\n }\r\n\r\n private setCursor(cursor: string) {\r\n this.map.getCanvas().style.cursor = cursor;\r\n }\r\n\r\n private onStyleLoad() {\r\n this.ensureLayers();\r\n this.bindLayerHandlers();\r\n this.render();\r\n }\r\n\r\n private emitChange() {\r\n this.onChange?.(this.getState());\r\n }\r\n\r\n private ensureLayers() {\r\n const style = { ...DEFAULT_STYLE, ...this.style };\r\n\r\n if (!this.map.getSource(this.linesSourceId)) {\r\n this.map.addSource(this.linesSourceId, {\r\n type: \"geojson\",\r\n data: emptyFeatureCollection<GeoJsonLineStringGeometry>(),\r\n });\r\n }\r\n\r\n if (!this.map.getSource(this.fillsSourceId)) {\r\n this.map.addSource(this.fillsSourceId, {\r\n type: \"geojson\",\r\n data: emptyFeatureCollection<GeoJsonPolygonGeometry>(),\r\n });\r\n }\r\n\r\n if (!this.map.getSource(this.pointsSourceId)) {\r\n this.map.addSource(this.pointsSourceId, {\r\n type: \"geojson\",\r\n data: emptyFeatureCollection<GeoJsonPointGeometry>(),\r\n });\r\n }\r\n\r\n if (!this.map.getSource(this.hoverPointSourceId)) {\r\n this.map.addSource(this.hoverPointSourceId, {\r\n type: \"geojson\",\r\n data: emptyFeatureCollection<GeoJsonPointGeometry>(),\r\n });\r\n }\r\n\r\n if (!this.map.getLayer(this.fillsLayerId)) {\r\n this.map.addLayer({\r\n id: this.fillsLayerId,\r\n type: \"fill\",\r\n source: this.fillsSourceId,\r\n paint: {\r\n \"fill-color\": style.fillColor,\r\n \"fill-opacity\": style.fillOpacity,\r\n },\r\n });\r\n }\r\n\r\n if (!this.map.getLayer(this.linesCasingLayerId)) {\r\n this.map.addLayer({\r\n id: this.linesCasingLayerId,\r\n type: \"line\",\r\n source: this.linesSourceId,\r\n layout: { \"line-cap\": \"round\", \"line-join\": \"round\" },\r\n paint: {\r\n \"line-color\": \"#FFFFFF\",\r\n \"line-width\": style.lineWidth + 3,\r\n \"line-opacity\": 0.9,\r\n },\r\n });\r\n }\r\n\r\n if (!this.map.getLayer(this.linesLayerId)) {\r\n this.map.addLayer({\r\n id: this.linesLayerId,\r\n type: \"line\",\r\n source: this.linesSourceId,\r\n layout: { \"line-cap\": \"round\", \"line-join\": \"round\" },\r\n paint: {\r\n \"line-color\": style.lineColor,\r\n \"line-width\": style.lineWidth,\r\n ...(this.style.lineDasharray ? { \"line-dasharray\": this.style.lineDasharray } : {}),\r\n },\r\n });\r\n }\r\n\r\n if (!this.map.getLayer(this.hoverPointLayerId)) {\r\n this.map.addLayer({\r\n id: this.hoverPointLayerId,\r\n type: \"circle\",\r\n source: this.hoverPointSourceId,\r\n paint: {\r\n \"circle-radius\": Math.max(3, style.pointRadius - 1),\r\n \"circle-color\": style.pointColor,\r\n \"circle-stroke-color\": style.pointStrokeColor,\r\n \"circle-stroke-width\": style.pointStrokeWidth,\r\n \"circle-opacity\": 0.8,\r\n \"circle-stroke-opacity\": 0.8,\r\n },\r\n });\r\n }\r\n\r\n if (!this.map.getLayer(this.pointsLayerId)) {\r\n this.map.addLayer({\r\n id: this.pointsLayerId,\r\n type: \"circle\",\r\n source: this.pointsSourceId,\r\n paint: {\r\n \"circle-radius\": style.pointRadius,\r\n \"circle-color\": style.pointColor,\r\n \"circle-stroke-color\": style.pointStrokeColor,\r\n \"circle-stroke-width\": style.pointStrokeWidth,\r\n },\r\n });\r\n }\r\n\r\n }\r\n\r\n private removeLayers() {\r\n [\r\n this.pointsLayerId,\r\n this.hoverPointLayerId,\r\n this.linesLayerId,\r\n this.linesCasingLayerId,\r\n this.fillsLayerId,\r\n ].forEach((layerId) => {\r\n if (this.map.getLayer(layerId)) {\r\n this.map.removeLayer(layerId);\r\n }\r\n });\r\n\r\n [\r\n this.pointsSourceId,\r\n this.hoverPointSourceId,\r\n this.linesSourceId,\r\n this.fillsSourceId,\r\n ].forEach((sourceId) => {\r\n if (this.map.getSource(sourceId)) {\r\n this.map.removeSource(sourceId);\r\n }\r\n });\r\n }\r\n\r\n private setSourceData<G>(sourceId: string, data: GeoJsonFeatureCollection<G>) {\r\n const source = this.map.getSource(sourceId) as GeoJSONSource | undefined;\r\n source?.setData(data as never);\r\n }\r\n\r\n private buildLineFeature(shape: MeasureShape): GeoJsonFeature<GeoJsonLineStringGeometry> | null {\r\n if (shape.points.length < 2) {\r\n return null;\r\n }\r\n\r\n const coordinates = shape.points.map((point) => point.lngLat);\r\n\r\n return {\r\n type: \"Feature\",\r\n id: shape.id,\r\n properties: { shapeId: shape.id },\r\n geometry: {\r\n type: \"LineString\",\r\n coordinates: shape.closed ? [...coordinates, coordinates[0] as [number, number]] : coordinates,\r\n },\r\n };\r\n }\r\n\r\n private buildFillFeature(shape: MeasureShape): GeoJsonFeature<GeoJsonPolygonGeometry> | null {\r\n if (shape.mode !== \"area\" || shape.points.length < 3) {\r\n return null;\r\n }\r\n\r\n const coordinates = shape.points.map((point) => point.lngLat);\r\n\r\n return {\r\n type: \"Feature\",\r\n id: shape.id,\r\n properties: { shapeId: shape.id },\r\n geometry: {\r\n type: \"Polygon\",\r\n coordinates: [[...coordinates, coordinates[0] as [number, number]]],\r\n },\r\n };\r\n }\r\n\r\n private buildPointFeatures(shape: MeasureShape): GeoJsonFeature<GeoJsonPointGeometry>[] {\r\n return shape.points.map((point) => ({\r\n type: \"Feature\",\r\n id: point.id,\r\n properties: { shapeId: shape.id, pointId: point.id },\r\n geometry: { type: \"Point\", coordinates: point.lngLat },\r\n }));\r\n }\r\n\r\n private getShapeAnchor(shape: MeasureShape): [number, number] {\r\n const coordinates = shape.points.map((point) => point.lngLat);\r\n\r\n return shape.mode === \"area\" ? polygonCentroid(coordinates) : midpoint(coordinates);\r\n }\r\n\r\n private render() {\r\n const shapes = this.shapes;\r\n\r\n const lineFeatures = shapes\r\n .map((shape) => this.buildLineFeature(shape))\r\n .filter((feature): feature is GeoJsonFeature<GeoJsonLineStringGeometry> => Boolean(feature));\r\n const fillFeatures = shapes\r\n .map((shape) => this.buildFillFeature(shape))\r\n .filter((feature): feature is GeoJsonFeature<GeoJsonPolygonGeometry> => Boolean(feature));\r\n const pointFeatures = shapes.flatMap((shape) => this.buildPointFeatures(shape));\r\n\r\n if (this.draft) {\r\n const draftLine = this.buildLineFeature(this.draft);\r\n const draftFill = this.buildFillFeature(this.draft);\r\n\r\n if (draftLine) lineFeatures.push(draftLine);\r\n if (draftFill) fillFeatures.push(draftFill);\r\n pointFeatures.push(...this.buildPointFeatures(this.draft));\r\n }\r\n\r\n this.setSourceData(this.linesSourceId, { type: \"FeatureCollection\", features: lineFeatures });\r\n this.setSourceData(this.fillsSourceId, { type: \"FeatureCollection\", features: fillFeatures });\r\n this.setSourceData(this.pointsSourceId, { type: \"FeatureCollection\", features: pointFeatures });\r\n\r\n this.updateBadge();\r\n this.syncShapeBadges();\r\n }\r\n\r\n private syncShapeBadges() {\r\n const activeIds = new Set(this.shapes.map((shape) => shape.id));\r\n\r\n Array.from(this.shapeBadges.keys()).forEach((shapeId) => {\r\n if (!activeIds.has(shapeId)) {\r\n this.shapeBadges.get(shapeId)?.destroy();\r\n this.shapeBadges.delete(shapeId);\r\n }\r\n });\r\n\r\n this.shapes.forEach((shape) => {\r\n if (shape.points.length < minShapePoints(shape.mode)) {\r\n this.shapeBadges.get(shape.id)?.destroy();\r\n this.shapeBadges.delete(shape.id);\r\n return;\r\n }\r\n\r\n const value =\r\n shape.mode === \"area\" ? formatArea(shape.area, this.labels) : formatDistance(shape.distance, this.labels);\r\n\r\n let shapeBadge = this.shapeBadges.get(shape.id);\r\n if (!shapeBadge) {\r\n shapeBadge = new MeasureShapeBadge(this.map.getContainer(), this.style, this.icons, () =>\r\n this.removeShape(shape.id),\r\n );\r\n this.shapeBadges.set(shape.id, shapeBadge);\r\n }\r\n\r\n shapeBadge.setValue(value);\r\n const projected = this.map.project(this.getShapeAnchor(shape));\r\n shapeBadge.setPosition(projected.x, projected.y);\r\n });\r\n }\r\n\r\n private updateShapeBadgePositions() {\r\n this.shapes.forEach((shape) => {\r\n const shapeBadge = this.shapeBadges.get(shape.id);\r\n if (!shapeBadge) {\r\n return;\r\n }\r\n\r\n const projected = this.map.project(this.getShapeAnchor(shape));\r\n shapeBadge.setPosition(projected.x, projected.y);\r\n });\r\n }\r\n\r\n private updateBadge() {\r\n if (!this.badge) {\r\n return;\r\n }\r\n\r\n if (!this.isActive || !this.draft || this.draft.points.length === 0) {\r\n this.badge.hide();\r\n return;\r\n }\r\n\r\n const isValid = this.draft.points.length >= minShapePoints(this.draft.mode);\r\n const value =\r\n this.draft.mode === \"area\"\r\n ? formatArea(this.draft.area, this.labels)\r\n : formatDistance(this.draft.distance, this.labels);\r\n\r\n this.badge.setValue(isValid ? value : formatDistance(this.draft.distance, this.labels));\r\n this.badge.setCheckEnabled(isValid);\r\n this.badge.show();\r\n this.updateBadgePosition();\r\n }\r\n\r\n private updateBadgePosition() {\r\n if (!this.badge || !this.draft || this.draft.points.length === 0 || !this.isActive) {\r\n return;\r\n }\r\n\r\n const lastPoint = this.draft.points[this.draft.points.length - 1];\r\n if (!lastPoint) {\r\n return;\r\n }\r\n\r\n const projected = this.map.project(lastPoint.lngLat);\r\n this.badge.setPosition(projected.x, projected.y);\r\n }\r\n}\r\n"],"mappings":"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","names":["index_exports","__export","MahalMap","MahalMapDefaultMarker","MeasureTool","Router","Search","SearchByLocation","services_exports","measure_exports","utils_exports","__toCommonJS","CameraController","map","zoom","smooth","bearing","pitch","is3D","options","BASE_URL","LATLNGREGEX","LNGLATREGEX","DARK","LIGHT","VECTOR","GRAM_BASE","GRAM_PRESETS","GRAM_KEY_PATHS","buildGramStyleUrl","base","preset","buildGramTransformRequest","apiKey","normalizedBase","url","isRelative","absoluteUrl","path","keyPath","appendQueryParam","styleUrl","name","value","separator","buildStyleUrl","lang","token","finalStyleUrl","apiKey","saveKey","param","clearKey","getApiKey","SVG_ROOT_PATTERN","SVG_MARKUP_PATTERN","updateSvgAttribute","svg","attribute","value","attributePattern","escapeSvgAttribute","createImageTag","url","normalizeInnerSvg","trimmedSvg","normalizedSvg","resolveInnerIcon","innerSvg","innerUrl","trimmedInnerSvg","trimmedInnerUrl","createDefaultMarkerSvg","color","innerIconOptions","MahalMapDefaultMarker","props","el","svg","createDefaultMarkerSvg","addMarker","maplibregl","map","marker","defaultStyles","DARK","LIGHT","logoColors","_MahalMap","GRAM_BASE","GRAM_PRESETS","options","lang","theme","buildStyleUrl","VECTOR","token","getApiKey","explicit","globalNs","maplibreObject","maps3dCtor","globalMaplibre","maplibre","language","engine","instance","instanceKey","enable3D","finalStyle","buildGramStyleUrl","transformRequest","buildGramTransformRequest","defaultPitch","CameraController","cb","container","callback","check","marker","enabled","center","zoom","addMarker","map","layer","error","visible","layers","isMaps3DLayer","sourceLayer","isBuildingLayer","logoHost","logoShadow","style","color","MahalMap","services_exports","__export","Router","Search","SearchByLocation","clearKey","getApiKey","saveKey","import_axios","api","axios","BASE_URL","routingApi","param","token","points","e","api","err","utils_exports","__export","checkCoordinates","debounce","geojsonPolyline","geometryPolyline_default","trimValue","checkCoordinates","coordinates","lat","lng","LATLNGREGEX","match","LNGLATREGEX","debounce","fn","delay","timer","args","resolve","result","geojsonPolyline","encoded","points","index","len","lat","lng","b","shift","result","dlat","dlng","geometryPolyline","coordinates","encoded","prevLat","prevLng","i","lng","lat","latE5","lngE5","dLat","dLng","encodeSignedNumber","num","sgnNum","encodeNumber","geometryPolyline_default","trimValue","value","cut","cleanValue","Router","param","typeData","token","res","routingApi","route","updated","r","geojsonPolyline","error","searchPost","params","api","error","searchByLocationPost","getSearch","param","token","additionalParam","searchData","searchPost","error","debouncedFn","debounce","Search","SearchByLocation","params","searchByLocationPost","measure_exports","__export","MeasureTool","haversineDistance","lineLength","midpoint","polygonArea","polygonCentroid","EARTH_RADIUS_M","toRadians","deg","normalizeLngDeltaDeg","deltaDeg","normalizeLngDeg","lngDeg","haversineDistance","a","b","lng1","lat1","lng2","lat2","phi1","phi2","deltaPhi","deltaLambda","sinDeltaPhi","sinDeltaLambda","centralAngleSegment","centralAngle","lineLength","points","total","i","polygonArea","p1","p2","vertexAverage","acc","point","polygonCentroid","referenceLng","unwrapped","lng","lat","signedAreaSum","cxSum","cySum","x0","y0","x1","y1","cross","signedArea","centroidLng","centroidLat","midpoint","segmentLengths","totalLength","length","targetLength","traversed","segmentLength","t","ALLOWED_TAGS","ALLOWED_ATTRS","URL_SENSITIVE_ATTRS","isSafeValue","attrName","value","normalized","sanitizeElement","element","attribute","name","child","sanitizeSvgMarkup","svg","doc","root","resolveIconMarkup","custom","fallback","DEFAULT_TRASH_SVG","DEFAULT_CLOSE_SVG","DEFAULT_CHECK_SVG","MeasureBadge","container","style","icons","callbacks","resolveIconMarkup","stop","event","el","button","size","text","enabled","x","y","MeasureShapeBadge","onRemove","wrapperStyle","valueStyle","buttonStyle","idCounter","nextId","prefix","instanceCounter","nextDefaultPrefix","DEFAULT_STYLE","formatDistance","meters","labels","formatArea","squareMeters","minShapePoints","mode","emptyFeatureCollection","MeasureTool","map","options","event","shape","point","item","MeasureBadge","modeChanged","shapeId","pointId","shapeBadge","coordinates","polygonArea","lineLength","feature","lngLat","projected","p","a","b","abx","aby","lengthSquared","t","screenPoint","segmentCount","bestIndex","bestScreen","bestDistance","i","candidate","dx","dy","distance","closest","newPoint","features","cursor","style","layerId","sourceId","data","polygonCentroid","midpoint","shapes","lineFeatures","fillFeatures","pointFeatures","draftLine","draftFill","activeIds","value","MeasureShapeBadge","isValid","lastPoint"]}
|