mahal_map 2.0.1 → 2.0.3

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 CHANGED
@@ -68,15 +68,15 @@ maplibregl.setWorkerUrl("/maplibre-gl-worker.mjs"); // файл скопиров
68
68
 
69
69
  Собственных URL стилей у `mahal_map` больше нет — их целиком отдаёт `@grammaps/maps3d-web`.
70
70
 
71
- | 1.x | 2.0 |
72
- | ---------------------------------------------- | -------------------------------------------------------------- |
73
- | `engine: "legacy"` (по умолчанию) | Удалён. Единственный путь — платформа через `Maps3D`. |
74
- | `engine: "3d"` | Больше не нужен, опция игнорируется. |
75
- | `autoAddVectorSource: true` | Удалён. Тот же векторный стиль применяется сам, когда нет `Maps3D`. |
76
- | `preset: "standard-night"` | `theme: "dark"`, либо полный URL в `style`. |
77
- | `preset: "road-urban-lab-v2"` | `theme: "light"`, либо полный URL в `style`. |
78
- | `lang` менял URL стиля | Стиль не трогает — язык подписей приходит из самого стиля. |
79
- | `layer.setBuildingsEnabled(...)` напрямую | `map.toggle3DBuildings(...)` или `map.setLayer("buildings", ...)`. |
71
+ | 1.x | 2.0 |
72
+ | ----------------------------------------- | ------------------------------------------------------------------- |
73
+ | `engine: "legacy"` (по умолчанию) | Удалён. Единственный путь — платформа через `Maps3D`. |
74
+ | `engine: "3d"` | Больше не нужен, опция игнорируется. |
75
+ | `autoAddVectorSource: true` | Удалён. Тот же векторный стиль применяется сам, когда нет `Maps3D`. |
76
+ | `preset: "standard-night"` | `theme: "dark"`, либо полный URL в `style`. |
77
+ | `preset: "road-urban-lab-v2"` | `theme: "light"`, либо полный URL в `style`. |
78
+ | `lang` менял URL стиля | Стиль не трогает — язык подписей приходит из самого стиля. |
79
+ | `layer.setBuildingsEnabled(...)` напрямую | `map.toggle3DBuildings(...)` или `map.setLayer("buildings", ...)`. |
80
80
 
81
81
  `engine` и `autoAddVectorSource` оставлены в типах как `@deprecated`, чтобы не ломать компиляцию, но на поведение не влияют.
82
82
 
@@ -203,42 +203,50 @@ interface IMahalMapOptions {
203
203
  antialias?: boolean;
204
204
  workerCheck?: boolean | number;
205
205
  maps3d?: Omit<IMaps3DLayerOptions, "apiKey" | "base">;
206
+ /** @deprecated Оставлена для совместимости, на поведение не влияет. */
207
+ engine?: "legacy" | "3d";
208
+ /** @deprecated Оставлена для совместимости, на поведение не влияет. */
209
+ autoAddVectorSource?: boolean;
206
210
  }
207
211
  ```
208
212
 
209
- | Параметр | Тип | Описание |
210
- | ----------- | ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
211
- | `container` | `string \| HTMLElement` | ID контейнера или DOM-элемент. Не передан — берётся `"map"`. |
212
- | `style` | `string` | Полный URL своего стиля. Задан — стиль зафиксирован, `setStyle()` его не меняет. |
213
- | `theme` | `"dark" \| "light"` | Светлая/тёмная внутри выбранного `family`. По умолчанию `light`. |
214
- | `lang` | `"tj" \| "ru"` | Язык для поиска и роутинга. На стиль не влияет — подписи приходят из самого стиля платформы. |
215
- | `center` | `[number, number]` | Центр карты в формате `[lng, lat]`. |
216
- | `zoom` | `number` | Начальный zoom. |
217
- | `pitch` | `number` | Начальный наклон камеры. Не задан и 3D включено — авто `58`: при `pitch: 0` объём зданий не виден, камера смотрит строго сверху. |
218
- | `bearing` | `number` | Начальный поворот камеры. |
219
- | `enable3D` | `boolean` | Подключает Maps3D. По умолчанию `true`, когда `Maps3D` доступен. |
220
- | `base` | `string` | Домен платформы. По умолчанию `https://navi.gram.tj`. |
221
- | `family` | `"default" \| "navigator" \| "mobile"` | Семейство стилей. `theme` выбирает внутри него: `default` → `light`/`dark`, `navigator` → `navigator-light`/`navigator-dark`, `mobile` → `mobile-*`. |
222
- | `preset` | `Maps3DThemeName \| string` | Явное имя темы платформы или полный URL стиля вместо пары `family` + `theme`. Задан — стиль зафиксирован. |
223
- | `antialias` | `boolean` | Сглаживание сцены. По умолчанию `true` при включённом 3D: без него тонкая геометрия (перила, мачты, ряды сидений) на отдалении рассыпается в рябь. |
224
- | `workerCheck` | `boolean \| number` | Диагностика неработающего веб-воркера MapLibre через 8 с после создания карты. `false` отключает, число задаёт свою задержку в мс. См. [Веб-воркер MapLibre](#веб-воркер-maplibre). |
225
- | `maps3d` | `object` | Опции Maps3D: `buildings`, `traffic`, `indoor`, `closures`, `places`, `minZoom`, `lodBias`, `memoryBudget`, `maskReplaced`, `typeReplacements`. |
213
+ | Параметр | Тип | Описание |
214
+ | ------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
215
+ | `container` | `string \| HTMLElement` | ID контейнера или DOM-элемент. Не передан — берётся `"map"`. |
216
+ | `style` | `string` | Полный URL своего стиля. Задан — стиль зафиксирован, `setStyle()` его не меняет. |
217
+ | `theme` | `"dark" \| "light"` | Светлая/тёмная внутри выбранного `family`. По умолчанию `light`. |
218
+ | `lang` | `"tj" \| "ru"` | Язык для поиска и роутинга. На стиль не влияет — подписи приходят из самого стиля платформы. |
219
+ | `center` | `[number, number]` | Центр карты в формате `[lng, lat]`. |
220
+ | `zoom` | `number` | Начальный zoom. |
221
+ | `pitch` | `number` | Начальный наклон камеры. Не задан и 3D включено — авто `58`: при `pitch: 0` объём зданий не виден, камера смотрит строго сверху. |
222
+ | `bearing` | `number` | Начальный поворот камеры. |
223
+ | `enable3D` | `boolean` | Подключает Maps3D. По умолчанию `true`, когда `Maps3D` доступен. |
224
+ | `base` | `string` | Домен платформы. По умолчанию `https://navi.gram.tj`. |
225
+ | `family` | `"default" \| "navigator" \| "mobile"` | Семейство стилей. `theme` выбирает внутри него: `default` → `light`/`dark`, `navigator` → `navigator-light`/`navigator-dark`, `mobile` → `mobile-*`. |
226
+ | `preset` | `Maps3DThemeName \| string` | Явное имя темы платформы или полный URL стиля вместо пары `family` + `theme`. Задан — стиль зафиксирован. |
227
+ | `antialias` | `boolean` | Сглаживание сцены. По умолчанию `true` при включённом 3D: без него тонкая геометрия (перила, мачты, ряды сидений) на отдалении рассыпается в рябь. |
228
+ | `workerCheck` | `boolean \| number` | Диагностика неработающего веб-воркера MapLibre через 8 с после создания карты. `false` отключает, число задаёт свою задержку в мс. См. [Веб-воркер MapLibre](#веб-воркер-maplibre). |
229
+ | `maps3d` | `object` | Опции Maps3D: `buildings`, `traffic`, `indoor`, `closures`, `places`, `minZoom`, `lodBias`, `memoryBudget`, `maskReplaced`, `typeReplacements`. |
226
230
 
227
231
  ### Стили и темы
228
232
 
229
233
  Стили целиком приходят из `@grammaps/maps3d-web` — своего списка URL у `mahal_map` больше нет. Словарь тем один и тот же у SDK и у библиотеки:
230
234
 
231
- | `family` | `theme: "light"` | `theme: "dark"` |
232
- | ------------- | ------------------ | ----------------- |
233
- | `"default"` | `light` | `dark` |
234
- | `"navigator"` | `navigator-light` | `navigator-dark` |
235
- | `"mobile"` | `mobile-light` | `mobile-dark` |
235
+ | `family` | `theme: "light"` | `theme: "dark"` |
236
+ | ------------- | ----------------- | ---------------- |
237
+ | `"default"` | `light` | `dark` |
238
+ | `"navigator"` | `navigator-light` | `navigator-dark` |
239
+ | `"mobile"` | `mobile-light` | `mobile-dark` |
236
240
 
237
241
  Имя темы уходит в `Maps3D.styleUrl()`, адрес строит сам SDK. Неизвестное имя — явная ошибка с префиксом `[MahalMap SDK]`, а не пустая карта.
238
242
 
239
243
  ```ts
240
244
  // Навигаторная тёмная тема
241
- MahalMap.create({ container: "map", family: "navigator", theme: "dark" }, maplibregl, Maps3D);
245
+ MahalMap.create(
246
+ { container: "map", family: "navigator", theme: "dark" },
247
+ maplibregl,
248
+ Maps3D,
249
+ );
242
250
 
243
251
  // Смена темы внутри того же семейства
244
252
  map.setStyle("light"); // → navigator-light
@@ -248,7 +256,10 @@ map.setStyle("light"); // → navigator-light
248
256
  >
249
257
  > ```ts
250
258
  > MahalMap.create(
251
- > { container: "map", style: "https://navi.gram.tj/maps/standard-night.json" },
259
+ > {
260
+ > container: "map",
261
+ > style: "https://navi.gram.tj/maps/standard-night.json",
262
+ > },
252
263
  > maplibregl,
253
264
  > Maps3D,
254
265
  > );
@@ -264,18 +275,18 @@ map.setStyle("light"); // → navigator-light
264
275
 
265
276
  Передаются в `MahalMap.create({ maps3d: {...} })` и уходят в `Maps3D` как есть:
266
277
 
267
- | Опция | Тип | По умолч. | Описание |
268
- | ------------------ | ----------------------------------------------------- | --------- | -------------------------------------------------------------------- |
269
- | `buildings` | `boolean \| { detail?: footprint\|volume\|roofs\|facade }` | `true` | Объёмные здания; объектом — их облик. |
270
- | `traffic` | `boolean \| { raster?, rasterMaxZoom?, graph?, opacity?, arrows? }` | `false` | Слой пробок. `raster: true` — картинкой вместо векторного слоя. |
271
- | `indoor` | `boolean \| { level? }` | `false` | Планы этажей. |
272
- | `closures` | `boolean \| object` | `false` | Перекрытия дорог. |
273
- | `places` | `object` | — | Парковки, заправки, зарядки: `highlight`, `paid`, `free`, `unknown`. |
274
- | `minZoom` | `number` | `16` | Зум появления объёма. |
275
- | `lodBias` | `number` | `1` | `0` — всегда детальная геометрия, `1` — упрощённая вдали. |
276
- | `memoryBudget` | `number` | `30` | Сколько 3D-моделей держать в памяти. |
277
- | `maskReplaced` | `boolean` | `true` | Прятать заменённые OSM-объекты (`anchor=replace`). |
278
- | `typeReplacements` | `boolean` | `true` | Рисовать замены по типу (`natural=tree` → 3D-дерево и т.п.). |
278
+ | Опция | Тип | По умолч. | Описание |
279
+ | ------------------ | ------------------------------------------------------------------- | --------- | -------------------------------------------------------------------- |
280
+ | `buildings` | `boolean \| { detail?: footprint\|volume\|roofs\|facade }` | `true` | Объёмные здания; объектом — их облик. |
281
+ | `traffic` | `boolean \| { raster?, rasterMaxZoom?, graph?, opacity?, arrows? }` | `false` | Слой пробок. `raster: true` — картинкой вместо векторного слоя. |
282
+ | `indoor` | `boolean \| { level? }` | `false` | Планы этажей. |
283
+ | `closures` | `boolean \| object` | `false` | Перекрытия дорог. |
284
+ | `places` | `object` | — | Парковки, заправки, зарядки: `highlight`, `paid`, `free`, `unknown`. |
285
+ | `minZoom` | `number` | `16` | Зум появления объёма. |
286
+ | `lodBias` | `number` | `1` | `0` — всегда детальная геометрия, `1` — упрощённая вдали. |
287
+ | `memoryBudget` | `number` | `30` | Сколько 3D-моделей держать в памяти. |
288
+ | `maskReplaced` | `boolean` | `true` | Прятать заменённые OSM-объекты (`anchor=replace`). |
289
+ | `typeReplacements` | `boolean` | `true` | Рисовать замены по типу (`natural=tree` → 3D-дерево и т.п.). |
279
290
 
280
291
  `apiKey` и `base` в `maps3d` передавать не нужно — их подставляет сам `MahalMap` из сохранённого ключа и `options.base`.
281
292
 
@@ -293,17 +304,19 @@ map.getLayerState("terrain"); // снимок одного слоя или null
293
304
  map.getLayers(); // снимок всех — по нему рисуется панель слоёв
294
305
  ```
295
306
 
296
- | Слой | Параметры | По умолчанию |
297
- | ------------------ | ------------------------------------------ | ------------ |
298
- | `buildings` | `detail: footprint\|volume\|roofs\|facade` | включён |
299
- | `objects` | — | включён |
300
- | `traffic` | | выключен |
301
- | `trafficRaster` | — | выключен |
302
- | `parking` | `highlight`, `paid`, `free`, `unknown` | включён |
303
- | `fuel`, `charging` | — | включены |
304
- | `closures` | — | выключен |
305
- | `indoor` | `level` | выключен |
306
- | `terrain` | `mode: auto\|on\|off` | `auto` |
307
+ | Слой | Параметры | По умолчанию | Откуда умолчание |
308
+ | ------------------ | ------------------------------------------ | ---------------------------------------------------------------------- | ----------------------- |
309
+ | `buildings` | `detail: footprint\|volume\|roofs\|facade` | включён | зашито |
310
+ | `objects` | — | включён | зашито |
311
+ | `terrain` | `mode: auto\|on\|off` | включён, `mode: "auto"` | зашито |
312
+ | `parking` | `highlight`, `paid`, `free`, `unknown` | включён, `{ highlight: false, paid: true, free: true, unknown: true }` | зашито |
313
+ | `fuel`, `charging` | | включены | зашито |
314
+ | `traffic` | — | выключен | `maps3d.traffic` |
315
+ | `trafficRaster` | — | выключен | `maps3d.traffic.raster` |
316
+ | `indoor` | `level` | выключен | `maps3d.indoor` |
317
+ | `closures` | — | выключен | `maps3d.closures` |
318
+
319
+ У нижних четырёх умолчание не зашито — реестр берёт его из опций `maps3d`, переданных при создании карты. Поэтому «выключен» в таблице значит «выключен, пока вы не передали опцию», а не «выключен всегда».
307
320
 
308
321
  Стартовое состояние можно задать сразу при создании карты — тогда первый кадр уже правильный, без моргания:
309
322
 
@@ -321,11 +334,11 @@ MahalMap.create(
321
334
 
322
335
  Поля независимы, и это главная ловушка реестра:
323
336
 
324
- | Поле | Вопрос |
325
- | ----------- | --------------------------------------- |
326
- | `wanted` | чего хочет приложение |
327
- | `available` | что позволяют стиль и данные |
328
- | `active` | что нарисовано прямо сейчас |
337
+ | Поле | Вопрос |
338
+ | ----------- | ---------------------------- |
339
+ | `wanted` | чего хочет приложение |
340
+ | `available` | что позволяют стиль и данные |
341
+ | `active` | что нарисовано прямо сейчас |
329
342
 
330
343
  Слой может быть включён и при этом не нарисован — и это не ошибка:
331
344
 
@@ -360,15 +373,20 @@ unsubscribe();
360
373
 
361
374
  Подтип парковки берётся из атрибута `fee`:
362
375
 
363
- | Параметр | Условие |
364
- | ----------- | --------------- |
365
- | `paid` | `fee=yes` |
366
- | `free` | `fee=no` |
367
- | `unknown` | атрибута нет |
376
+ | Параметр | Условие |
377
+ | --------- | ------------ |
378
+ | `paid` | `fee=yes` |
379
+ | `free` | `fee=no` |
380
+ | `unknown` | атрибута нет |
368
381
 
369
382
  ```ts
370
383
  // только платные, с подсветкой
371
- map.setLayer("parking", true, { paid: true, free: false, unknown: false, highlight: true });
384
+ map.setLayer("parking", true, {
385
+ paid: true,
386
+ free: false,
387
+ unknown: false,
388
+ highlight: true,
389
+ });
372
390
  ```
373
391
 
374
392
  #### Рельеф
@@ -477,7 +495,16 @@ map.roadAt({ x: 320, y: 240 });
477
495
  map.roadsNamed; // есть ли в текущем стиле названия дорог
478
496
  ```
479
497
 
480
- Подписываться можно сразу после `create()`, до готовности карты.
498
+ Подписываться можно сразу после `create()` даже когда слой ещё не поднят (`enable3D: false`). Подписка и облик выделения запоминаются и переигрываются, как только слой появится:
499
+
500
+ ```ts
501
+ const map = MahalMap.create({ container: "map", enable3D: false }, maplibregl, Maps3D);
502
+
503
+ map.onBuildingClick((b) => console.log(b?.props.osm_id));
504
+ map.setSelectionStyle({ color: "#e23b2f" });
505
+
506
+ map.toggle3DBuildings(true); // подписка и стиль выделения уже применены к новому слою
507
+ ```
481
508
 
482
509
  #### Вкл/выкл 3D-здания на лету
483
510
 
@@ -493,7 +520,15 @@ map.toggle3DBuildings(true); // вкл обратно
493
520
  MahalMap.toggle3DBuildings(map, false);
494
521
  ```
495
522
 
496
- Под капотом это `setLayer("buildings", enabled)`. Штатные здания стиля прячет и возвращает сам `Maps3D` — `mahal_map` их видимость не трогает, поэтому спорить за один слой некому. Эквивалентная запись: `map.setLayer("buildings", false)`.
523
+ Штатные здания стиля прячет и возвращает сам `Maps3D` — `mahal_map` их видимость не трогает, поэтому спорить за один слой некому.
524
+
525
+ Для переключения пользуйтесь именно `toggle3DBuildings()`: он поднимет слой, если его ещё не было (`enable3D: false` при создании), а на сборках Maps3D без реестра слоёв откатится на `setBuildingsEnabled()`.
526
+
527
+ ```ts
528
+ map.toggle3DBuildings(false); // совместимо со всеми сборками
529
+ ```
530
+
531
+ `map.setLayer("buildings", false)` — не замена: он ходит только в реестр и ничего не создаёт. Годится, когда вы точно знаете, что на странице Maps3D с реестром слоёв (0.7.x), и слой уже подключён.
497
532
 
498
533
  #### `map.whenMaps3DReady()`
499
534
 
@@ -660,15 +695,15 @@ onBeforeUnmount(() => {
660
695
 
661
696
  Что библиотека делает за вас против ручного подключения `@grammaps/maps3d-web`:
662
697
 
663
- | Ручной код | Через `mahal_map` |
664
- | --------------------------------------------------- | -------------------------------------------------------------- |
665
- | `...Maps3D.mapOptions({ base, apiKey, style })` | `theme` + `family` (или `preset` / `style` / `base` явно) |
666
- | `antialias: true` не забыть | ставится сам при включённом 3D |
667
- | `Maps3D.enhance(map, opts); await maps3d.ready` | `enable3D: true` + `maps3d: {...}`, `await map.whenMaps3DReady()` |
668
- | `map.setStyle(Maps3D.styleUrl("dark", base))` | `map.setStyle("dark")` — внутри выбранного семейства |
669
- | `maps3d.refreshLayers()` после смены стиля | вызывается сам на `style.load` |
670
- | `maps3d.destroy(); map.remove()` | `map.destroy()` |
671
- | ключ руками в каждый вызов | один `keyUtils.saveKey()` на всё |
698
+ | Ручной код | Через `mahal_map` |
699
+ | ----------------------------------------------- | ----------------------------------------------------------------- |
700
+ | `...Maps3D.mapOptions({ base, apiKey, style })` | `theme` + `family` (или `preset` / `style` / `base` явно) |
701
+ | `antialias: true` не забыть | ставится сам при включённом 3D |
702
+ | `Maps3D.enhance(map, opts); await maps3d.ready` | `enable3D: true` + `maps3d: {...}`, `await map.whenMaps3DReady()` |
703
+ | `map.setStyle(Maps3D.styleUrl("dark", base))` | `map.setStyle("dark")` — внутри выбранного семейства |
704
+ | `maps3d.refreshLayers()` после смены стиля | вызывается сам на `style.load` |
705
+ | `maps3d.destroy(); map.remove()` | `map.destroy()` |
706
+ | ключ руками в каждый вызов | один `keyUtils.saveKey()` на всё |
672
707
 
673
708
  #### То же самое без сборщика (browser SDK)
674
709
 
@@ -684,14 +719,18 @@ onBeforeUnmount(() => {
684
719
  <script type="module">
685
720
  const maplibregl = await Maps3D.maplibre({ base: "https://navi.gram.tj" });
686
721
 
687
- // Maps3D берётся из window.Maps3D третий аргумент передавать не нужно.
688
- const map = MahalMap.create({
689
- container: "map",
690
- theme: "dark",
691
- center: [68.787, 38.573],
692
- zoom: 16.6,
693
- pitch: 58,
694
- });
722
+ // maplibregl обязателен вторым аргументом: window.maplibregl здесь не появляется.
723
+ // Maps3D третьим можно не передавать — SDK возьмёт его из window.Maps3D.
724
+ const map = MahalMap.create(
725
+ {
726
+ container: "map",
727
+ theme: "dark",
728
+ center: [68.787, 38.573],
729
+ zoom: 16.6,
730
+ pitch: 58,
731
+ },
732
+ maplibregl,
733
+ );
695
734
 
696
735
  let enabled = true;
697
736
 
@@ -791,13 +830,13 @@ try {
791
830
 
792
831
  Правила проверки:
793
832
 
794
- | Условие | Поведение |
795
- | ------- | --------- |
796
- | `Maps3D` не передан, сервис ответил `success: true` | Карта создаётся на запасном стиле. |
797
- | `Maps3D` не передан, сервис ответил `success: false` | Карта **не** создаётся, промис отклоняется: `[MahalMap SDK] JSApi subscription is not active for this key: <message>`. |
798
- | `Maps3D` не передан, проверка не дошла (сеть, CORS, таймаут) | Fail-open: `console.warn` и карта создаётся. Падение сервиса проверки не гасит карты. |
799
- | `Maps3D` передан | Проверка **пропускается**, запрос не отправляется. |
800
- | Map token не сохранён | Проверка пропускается, дальше срабатывает обычная ошибка про `apikey`. |
833
+ | Условие | Поведение |
834
+ | ------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------- |
835
+ | `Maps3D` не передан, сервис ответил `success: true` | Карта создаётся на запасном стиле. |
836
+ | `Maps3D` не передан, сервис ответил `success: false` | Карта **не** создаётся, промис отклоняется: `[MahalMap SDK] JSApi subscription is not active for this key: <message>`. |
837
+ | `Maps3D` не передан, проверка не дошла (сеть, CORS, таймаут) | Fail-open: `console.warn` и карта создаётся. Падение сервиса проверки не гасит карты. |
838
+ | `Maps3D` передан | Проверка **пропускается**, запрос не отправляется. |
839
+ | Map token не сохранён | Проверка пропускается, дальше срабатывает обычная ошибка про `apikey`. |
801
840
 
802
841
  С переданным `Maps3D` вызов `createAsync()` ведёт себя ровно как `create()` — доступ к платформе контролируется параметром `?key=` на её стороне, отдельная подписка JSApi к ней отношения не имеет.
803
842
 
@@ -814,7 +853,9 @@ try {
814
853
  <div ref="mapElement" class="h-[360px] w-full" />
815
854
  </div>
816
855
  <template #fallback>
817
- <div class="flex h-[360px] items-center justify-center">{{ loadingLabel }}</div>
856
+ <div class="flex h-[360px] items-center justify-center">
857
+ {{ loadingLabel }}
858
+ </div>
818
859
  </template>
819
860
  </ClientOnly>
820
861
  </template>
@@ -1105,43 +1146,43 @@ MahalMap.setZoom(map, 14);
1105
1146
 
1106
1147
  Доступные функции карты в browser SDK:
1107
1148
 
1108
- | Функция | Описание |
1109
- | -------------------------------------- | ------------------------------------------------------------- |
1110
- | `create(options)` | Создает карту. Требует `apikey` в URL SDK скрипта. |
1111
- | `createAsync(options)` | Создает карту после проверки подписки JSApi (только без Maps3D). |
1112
- | `onReady(container, callback)` | Выполняет callback после загрузки карты. |
1113
- | `getInstance(container)` | Возвращает инстанс карты. |
1114
- | `hasInstance(container)` | Проверяет наличие инстанса. |
1115
- | `removeInstance(container)` | Удаляет инстанс из реестра. |
1116
- | `getMap(instance)` | Возвращает нативный MapLibre Map. |
1117
- | `getCamera(instance)` | Возвращает CameraController. |
1118
- | `setStyle(instance, theme)` | Переключает тему стандартного стиля. |
1119
- | `setLanguage(instance, lang)` | Переключает язык стандартного стиля. |
1120
- | `setCenter(instance, center)` | Меняет центр карты. |
1121
- | `setZoom(instance, zoom)` | Меняет zoom карты. |
1122
- | `addMarker(instance, marker)` | Добавляет маркер. |
1123
- | `getMaps3DLayer(instance)` | Возвращает инстанс слоя Maps3D (`undefined`, если Maps3D не передан). |
1124
- | `whenMaps3DReady(instance)` | Промис слоя Maps3D после `attach()` (готов `layer.buildings`). |
1125
- | `toggle3DBuildings(instance, enabled)` | Вкл/выкл объёмные здания на лету. |
1126
- | `setLayer(instance, id, on, params?)` | Включить/выключить слой платформы. |
1127
- | `getLayerState(instance, id)` | Снимок состояния одного слоя. |
1128
- | `getLayers(instance)` | Снимок всех слоёв. |
1129
- | `onLayers(instance, callback)` | Подписка на изменения слоёв; возвращает отписку. |
1130
- | `refreshLayers(instance)` | Пере-применить волю клиента ко всем слоям. |
1131
- | `getIndoorLevels(instance)` | Этажи, найденные в текущем виде карты. |
1132
- | `setIndoorLevel(instance, level)` | Переключить этаж (0 — первый наземный). |
1133
- | `refreshIndoor(instance)` | Перечитать планы этажей. |
1134
- | `showPlace(instance, lon, lat, level?, zoom?)` | Показать объект и открыть его этаж. |
1135
- | `onBuildingClick(instance, callback)` | Клик по зданию. |
1136
- | `selectBuilding(instance, id, style?)` | Выделить здание по `osm_id`. |
1137
- | `clearSelection(instance)` | Снять выделение. |
1138
- | `selectedBuilding(instance)` | Идентификатор выделенного здания или `null`. |
1139
- | `setSelectionStyle(instance, style)` | Облик выделения. |
1140
- | `onRoadClick(instance, callback)` | Клик по дороге. |
1141
- | `roadAt(instance, point, tolPx?)` | Дорога под точкой холста. |
1142
- | `destroy(instance)` | Полностью удаляет карту. |
1143
- | `loadKeyFromScriptUrl()` | Читает `apikey` из URL SDK скрипта. |
1144
- | `loadLanguageFromScriptUrl()` | Читает `lang` из URL SDK скрипта. |
1149
+ | Функция | Описание |
1150
+ | ---------------------------------------------- | --------------------------------------------------------------------- |
1151
+ | `create(options)` | Создает карту. Требует `apikey` в URL SDK скрипта. |
1152
+ | `createAsync(options)` | Создает карту после проверки подписки JSApi (только без Maps3D). |
1153
+ | `onReady(container, callback)` | Выполняет callback после загрузки карты. |
1154
+ | `getInstance(container)` | Возвращает инстанс карты. |
1155
+ | `hasInstance(container)` | Проверяет наличие инстанса. |
1156
+ | `removeInstance(container)` | Удаляет инстанс из реестра. |
1157
+ | `getMap(instance)` | Возвращает нативный MapLibre Map. |
1158
+ | `getCamera(instance)` | Возвращает CameraController. |
1159
+ | `setStyle(instance, theme)` | Переключает тему стандартного стиля. |
1160
+ | `setLanguage(instance, lang)` | Переключает язык стандартного стиля. |
1161
+ | `setCenter(instance, center)` | Меняет центр карты. |
1162
+ | `setZoom(instance, zoom)` | Меняет zoom карты. |
1163
+ | `addMarker(instance, marker)` | Добавляет маркер. |
1164
+ | `getMaps3DLayer(instance)` | Возвращает инстанс слоя Maps3D (`undefined`, если Maps3D не передан). |
1165
+ | `whenMaps3DReady(instance)` | Промис слоя Maps3D после `attach()` (готов `layer.buildings`). |
1166
+ | `toggle3DBuildings(instance, enabled)` | Вкл/выкл объёмные здания на лету. |
1167
+ | `setLayer(instance, id, on, params?)` | Включить/выключить слой платформы. |
1168
+ | `getLayerState(instance, id)` | Снимок состояния одного слоя. |
1169
+ | `getLayers(instance)` | Снимок всех слоёв. |
1170
+ | `onLayers(instance, callback)` | Подписка на изменения слоёв; возвращает отписку. |
1171
+ | `refreshLayers(instance)` | Пере-применить волю клиента ко всем слоям. |
1172
+ | `getIndoorLevels(instance)` | Этажи, найденные в текущем виде карты. |
1173
+ | `setIndoorLevel(instance, level)` | Переключить этаж (0 — первый наземный). |
1174
+ | `refreshIndoor(instance)` | Перечитать планы этажей. |
1175
+ | `showPlace(instance, lon, lat, level?, zoom?)` | Показать объект и открыть его этаж. |
1176
+ | `onBuildingClick(instance, callback)` | Клик по зданию. |
1177
+ | `selectBuilding(instance, id, style?)` | Выделить здание по `osm_id`. |
1178
+ | `clearSelection(instance)` | Снять выделение. |
1179
+ | `selectedBuilding(instance)` | Идентификатор выделенного здания или `null`. |
1180
+ | `setSelectionStyle(instance, style)` | Облик выделения. |
1181
+ | `onRoadClick(instance, callback)` | Клик по дороге. |
1182
+ | `roadAt(instance, point, tolPx?)` | Дорога под точкой холста. |
1183
+ | `destroy(instance)` | Полностью удаляет карту. |
1184
+ | `loadKeyFromScriptUrl()` | Читает `apikey` из URL SDK скрипта. |
1185
+ | `loadLanguageFromScriptUrl()` | Читает `lang` из URL SDK скрипта. |
1145
1186
 
1146
1187
  ## CameraController
1147
1188
 
@@ -1372,19 +1413,19 @@ const measureTool = new MeasureTool(map, {
1372
1413
 
1373
1414
  ### Методы
1374
1415
 
1375
- | Метод | Описание |
1376
- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
1377
- | `start(mode?)` | Включает инструмент и начинает/продолжает рисование в указанном режиме. |
1378
- | `stop()` | Выключает инструмент, прячет активный бейдж. Сохраненные фигуры остаются на карте. |
1379
- | `setMode(mode)` | Переключает режим. Если фигура уже рисуется — её точки сохраняются, меняется только тип (линия ⇄ полигон), как в Яндекс.Картах. |
1380
- | `finishDraft()` | Завершает текущую фигуру (если валидна — от 2 точек для линии, от 3 для полигона) и начинает новую. |
1381
- | `removeShape(shapeId)` | Удаляет фигуру (черновик или уже сохраненную) целиком. |
1382
- | `removePoint(shapeId, pointId)` | Удаляет одну точку фигуры. |
1383
- | `clearAll()` | Удаляет все фигуры и черновик. |
1384
- | `getState()` | Возвращает текущий `MeasureState` (снимок, без подписки). |
1416
+ | Метод | Описание |
1417
+ | ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1418
+ | `start(mode?)` | Включает инструмент и начинает/продолжает рисование в указанном режиме. |
1419
+ | `stop()` | Выключает инструмент, прячет активный бейдж. Сохраненные фигуры остаются на карте. |
1420
+ | `setMode(mode)` | Переключает режим. Если фигура уже рисуется — её точки сохраняются, меняется только тип (линия ⇄ полигон), как в Яндекс.Картах. |
1421
+ | `finishDraft()` | Завершает текущую фигуру (если валидна — от 2 точек для линии, от 3 для полигона) и начинает новую. |
1422
+ | `removeShape(shapeId)` | Удаляет фигуру (черновик или уже сохраненную) целиком. |
1423
+ | `removePoint(shapeId, pointId)` | Удаляет одну точку фигуры. |
1424
+ | `clearAll()` | Удаляет все фигуры и черновик. |
1425
+ | `getState()` | Возвращает текущий `MeasureState` (снимок, без подписки). |
1385
1426
  | `setStyleOptions(style)` | Обновляет палитру (частично, `Partial<MeasureStyleOptions>`) без пересоздания инструмента: перекрашивает существующие слои и бейджи. Нужен при смене темы карты. |
1386
- | `refresh()` | Пересоздает источники/слои и перерисовывает фигуры. Инструмент делает это сам после `setStyle()`; метод оставлен как страховка. |
1387
- | `destroy()` | Полностью снимает слои, обработчики и DOM-бейджи. Вызывать при размонтировании. Повторный вызов безопасен. |
1427
+ | `refresh()` | Пересоздает источники/слои и перерисовывает фигуры. Инструмент делает это сам после `setStyle()`; метод оставлен как страховка. |
1428
+ | `destroy()` | Полностью снимает слои, обработчики и DOM-бейджи. Вызывать при размонтировании. Повторный вызов безопасен. |
1388
1429
 
1389
1430
  ### Смена стиля карты (тема, язык)
1390
1431
 
@@ -1437,7 +1478,13 @@ interface MeasureShape {
1437
1478
  Сервисы работают независимо от карты: их можно вызывать без `MahalMap.create()`. Токен передаётся аргументом в каждый вызов — сохранённый через `keyUtils.saveKey()` map token для них не используется.
1438
1479
 
1439
1480
  ```ts
1440
- import { Search, SearchPoi, SearchByLocation, CheckJSApi, Router } from "mahal_map";
1481
+ import {
1482
+ Search,
1483
+ SearchPoi,
1484
+ SearchByLocation,
1485
+ CheckJSApi,
1486
+ Router,
1487
+ } from "mahal_map";
1441
1488
  ```
1442
1489
 
1443
1490
  ### `Search(text, token, additionalParam?)`
@@ -1452,13 +1499,13 @@ const results = await Search("Рудаки 33", token, {
1452
1499
  });
1453
1500
  ```
1454
1501
 
1455
- | Параметр | Тип | Описание |
1456
- | -------- | --- | -------- |
1457
- | `text` | `string` | Строка поиска. |
1458
- | `token` | `string` | Токен сервиса. Обязателен, иначе `[MahalMap SDK] Search token is required`. |
1459
- | `additionalParam.lat` / `.lng` | `string` | Точка для сортировки результатов по удалённости. |
1460
- | `additionalParam.limit` | `number` | Максимум результатов. |
1461
- | `additionalParam.type` | `string` | Фильтр по типу объекта. |
1502
+ | Параметр | Тип | Описание |
1503
+ | ------------------------------ | -------- | --------------------------------------------------------------------------- |
1504
+ | `text` | `string` | Строка поиска. |
1505
+ | `token` | `string` | Токен сервиса. Обязателен, иначе `[MahalMap SDK] Search token is required`. |
1506
+ | `additionalParam.lat` / `.lng` | `string` | Точка для сортировки результатов по удалённости. |
1507
+ | `additionalParam.limit` | `number` | Максимум результатов. |
1508
+ | `additionalParam.type` | `string` | Фильтр по типу объекта. |
1462
1509
 
1463
1510
  Возвращает `ISearchResponse[]`.
1464
1511
 
@@ -1467,7 +1514,11 @@ const results = await Search("Рудаки 33", token, {
1467
1514
  Поиск POI (организации, объекты). Сигнатура и дебаунс те же, что у `Search`, таймер отдельный — параллельный ввод в двух полях не перебивает запросы друг друга.
1468
1515
 
1469
1516
  ```ts
1470
- const places = await SearchPoi("кафе", token, { lat: "38.5598", lng: "68.7870", limit: 20 });
1517
+ const places = await SearchPoi("кафе", token, {
1518
+ lat: "38.5598",
1519
+ lng: "68.7870",
1520
+ limit: 20,
1521
+ });
1471
1522
  ```
1472
1523
 
1473
1524
  Возвращает `ISearchResponse[]`.
@@ -1484,12 +1535,12 @@ const res = await SearchByLocation({
1484
1535
  });
1485
1536
  ```
1486
1537
 
1487
- | Поле | Тип | Обязательное |
1488
- | ---- | --- | ------------ |
1489
- | `lat` | `string \| number` | да |
1490
- | `lng` | `string \| number` | да |
1491
- | `token` | `string` | да |
1492
- | `type` | `string` | нет |
1538
+ | Поле | Тип | Обязательное |
1539
+ | ------- | ------------------ | ------------ |
1540
+ | `lat` | `string \| number` | да |
1541
+ | `lng` | `string \| number` | да |
1542
+ | `token` | `string` | да |
1543
+ | `type` | `string` | нет |
1493
1544
 
1494
1545
  ### `CheckJSApi(token)`
1495
1546
 
@@ -1522,11 +1573,11 @@ const routes = await Router(
1522
1573
  );
1523
1574
  ```
1524
1575
 
1525
- | Параметр | Тип | Описание |
1526
- | -------- | --- | -------- |
1527
- | `points` | `number[][]` | Точки в формате `[lng, lat]`. |
1528
- | `typeData` | `string` | `"geojson"` — декодирует polyline в массив координат. Другое значение оставляет `geometry` строкой polyline. |
1529
- | `token` | `string` | Токен сервиса. |
1576
+ | Параметр | Тип | Описание |
1577
+ | ---------- | ------------ | ------------------------------------------------------------------------------------------------------------ |
1578
+ | `points` | `number[][]` | Точки в формате `[lng, lat]`. |
1579
+ | `typeData` | `string` | `"geojson"` — декодирует polyline в массив координат. Другое значение оставляет `geometry` строкой polyline. |
1580
+ | `token` | `string` | Токен сервиса. |
1530
1581
 
1531
1582
  Возвращает `IRoute[]`.
1532
1583