solid-map-gl 2.2.0 → 2.2.1

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.
@@ -1,38 +1,19 @@
1
+ import {
2
+ MapProvider,
3
+ useMapContext
4
+ } from "../chunk/N4NHJCAS.jsx";
5
+
1
6
  // src/components/MapGL/index.tsx
2
7
  import {
3
8
  createSignal,
4
- createEffect as createEffect2,
9
+ createEffect,
5
10
  onMount,
6
11
  onCleanup,
7
12
  on
8
13
  } from "solid-js";
9
14
  import { isServer } from "solid-js/web";
10
15
 
11
- // src/components/MapProvider/index.tsx
12
- import { createContext, useContext, createEffect } from "solid-js";
13
- import { createStore } from "solid-js/store";
14
- var defaultState = {
15
- map: null,
16
- mapLib: null,
17
- isMapLibre: false,
18
- constants: {},
19
- themeVersion: 0
20
- };
21
- var MapContext = createContext([defaultState]);
22
- var useMapContext = () => useContext(MapContext);
23
- var MapProvider = (props) => {
24
- const [state, setState] = createStore({ ...defaultState });
25
- props.map && setState("map", props.map);
26
- props.mapLib && setState("mapLib", props.mapLib);
27
- setState("isMapLibre", !!props.isMapLibre);
28
- setState("constants", props.constants || {});
29
- setState("themeVersion", props.themeVersion || 0);
30
- createEffect(() => setState("constants", props.constants || {}));
31
- createEffect(() => setState("themeVersion", props.themeVersion || 0));
32
- return <MapContext.Provider value={[state]}>{props.children}</MapContext.Provider>;
33
- };
34
-
35
- // src/events.ts
16
+ // src/lib/events.ts
36
17
  var mapEvents = [
37
18
  "onMouseDown",
38
19
  "onMouseUp",
@@ -111,7 +92,7 @@ var drawEvents = [
111
92
  "onActionable"
112
93
  ];
113
94
 
114
- // src/mapStyles.ts
95
+ // src/lib/mapStyles.ts
115
96
  var mapBase = "mapbox://styles/mapbox";
116
97
  var gitBase = "https://raw.githubusercontent.com/";
117
98
  var gishub = "https://raw.githubusercontent.com/GIShub4/map-styles/main/";
@@ -229,7 +210,7 @@ var rasterStyleList = {
229
210
  }
230
211
  };
231
212
 
232
- // src/tilesSettled.ts
213
+ // src/components/MapGL/tilesSettled.ts
233
214
  var nextFrame = () => new Promise((resolve) => requestAnimationFrame(() => resolve()));
234
215
  var hasActiveFadeTransition = (map) => {
235
216
  try {
@@ -289,7 +270,7 @@ function disableRasterFade(map) {
289
270
  }
290
271
  }
291
272
 
292
- // src/offscreenCapture.ts
273
+ // src/components/MapGL/offscreenCapture.ts
293
274
  function createCapturer(map, settleOptions) {
294
275
  return {
295
276
  map,
@@ -328,6 +309,14 @@ var MapGL = (props) => {
328
309
  ) || style : style;
329
310
  };
330
311
  onMount(async () => {
312
+ try {
313
+ await setupMap();
314
+ } catch (error) {
315
+ console.error("[MapGL] Failed to initialize map:", error);
316
+ props.onError?.(error);
317
+ }
318
+ });
319
+ const setupMap = async () => {
331
320
  mapLib = props.mapLib || await import("mapbox-gl");
332
321
  if (!mapLib.Map) mapLib = window["maplibregl"] || window["mapboxgl"];
333
322
  if (typeof mapLib.supported === "function" && !mapLib.supported())
@@ -361,7 +350,7 @@ var MapGL = (props) => {
361
350
  if (typeof prop === "function") {
362
351
  map.on(event, (evt) => {
363
352
  setTimeout(() => {
364
- if (evt.clickOnLayer) return;
353
+ if (event === "click" && evt.clickOnLayer) return;
365
354
  prop(evt);
366
355
  props.debugEvents && debug(`Map '${event}' event:`, evt);
367
356
  }, 0);
@@ -370,7 +359,7 @@ var MapGL = (props) => {
370
359
  Object.keys(prop).forEach((layerId) => {
371
360
  map.on(event, layerId, (evt) => {
372
361
  setTimeout(() => {
373
- if (evt.clickOnLayer) return;
362
+ if (event === "click" && evt.clickOnLayer) return;
374
363
  prop[layerId](evt);
375
364
  props.debugEvents && debug(`Map '${event}' event on '${layerId}':`, evt);
376
365
  }, 0);
@@ -481,12 +470,12 @@ var MapGL = (props) => {
481
470
  props.onViewportChange(viewport);
482
471
  });
483
472
  });
484
- });
485
- createEffect2(
473
+ };
474
+ createEffect(
486
475
  on(
487
476
  () => props.viewport,
488
477
  (vp) => {
489
- if (props.id !== vp?.id) return;
478
+ if (!map || props.id !== vp?.id) return;
490
479
  if (expectingOwnEcho) {
491
480
  expectingOwnEcho = false;
492
481
  return;
@@ -511,7 +500,7 @@ var MapGL = (props) => {
511
500
  { defer: true }
512
501
  )
513
502
  );
514
- createEffect2(() => {
503
+ createEffect(() => {
515
504
  const loadedMap = mapLoaded();
516
505
  if (typeof loadedMap?.setConfigProperty !== "function") {
517
506
  if (loadedMap && props.config && Object.keys(props.config).length) {
@@ -529,13 +518,13 @@ var MapGL = (props) => {
529
518
  debug(`Set Config (${id}:${key}) to:`, value);
530
519
  }
531
520
  });
532
- createEffect2(() => {
521
+ createEffect(() => {
533
522
  const proj = props.options?.projection;
534
523
  if (!map || !proj) return;
535
524
  map.setProjection(proj);
536
525
  debug("Set Projection to:", proj);
537
526
  });
538
- createEffect2(() => {
527
+ createEffect(() => {
539
528
  const cur = props.cursorStyle;
540
529
  if (!map || !cur) return;
541
530
  map.getCanvas().style.cursor = cur;
@@ -550,7 +539,7 @@ var MapGL = (props) => {
550
539
  });
551
540
  return list;
552
541
  };
553
- createEffect2((prev) => {
542
+ createEffect((prev) => {
554
543
  const style = getStyle(props.options?.style, props.darkStyle);
555
544
  if (map?.isStyleLoaded() && prev !== style) {
556
545
  const oldStyle = map.getStyle();
@@ -583,7 +572,7 @@ var MapGL = (props) => {
583
572
  "showPadding",
584
573
  "showOverdrawInspector"
585
574
  ].forEach((item) => {
586
- createEffect2(() => {
575
+ createEffect(() => {
587
576
  const prop = props[item];
588
577
  if (!map || !prop) return;
589
578
  map[item] = prop;
@@ -627,13 +616,13 @@ var MapGL = (props) => {
627
616
  // src/components/Source/index.tsx
628
617
  import {
629
618
  onCleanup as onCleanup2,
630
- createEffect as createEffect3,
631
- createContext as createContext2,
632
- useContext as useContext2,
619
+ createEffect as createEffect2,
620
+ createContext,
621
+ useContext,
633
622
  createUniqueId
634
623
  } from "solid-js";
635
- var SourceContext = createContext2();
636
- var useSourceId = () => useContext2(SourceContext);
624
+ var SourceContext = createContext();
625
+ var useSourceId = () => useContext(SourceContext);
637
626
  var Source = (props) => {
638
627
  const [ctx] = useMapContext();
639
628
  props.id ??= createUniqueId();
@@ -665,14 +654,14 @@ var Source = (props) => {
665
654
  debug("Add Source:", props.id);
666
655
  switch (anySource().type) {
667
656
  case "geojson":
668
- createEffect3(() => {
657
+ createEffect2(() => {
669
658
  const data = anySource().data;
670
659
  ctx.map.getSource(props.id).setData(data || {});
671
660
  debug("Update GeoJSON Data:", props.id);
672
661
  });
673
662
  break;
674
663
  case "image":
675
- createEffect3(() => {
664
+ createEffect2(() => {
676
665
  const url = anySource().url;
677
666
  const coords = anySource().coordinates;
678
667
  ctx.map.getSource(props.id).updateImage(url, coords);
@@ -680,7 +669,7 @@ var Source = (props) => {
680
669
  });
681
670
  break;
682
671
  case "vector":
683
- createEffect3(() => {
672
+ createEffect2(() => {
684
673
  const url = anySource().url;
685
674
  const tiles = anySource().tiles;
686
675
  const source = ctx.map.getSource(props.id);
@@ -689,7 +678,7 @@ var Source = (props) => {
689
678
  });
690
679
  break;
691
680
  case "raster":
692
- createEffect3(() => {
681
+ createEffect2(() => {
693
682
  const src = lookup(anySource().url);
694
683
  const source = ctx.map.getSource(props.id);
695
684
  src.url ? source.setUrl(src.url) : source.setTiles(src.tiles);
@@ -712,12 +701,12 @@ var Source = (props) => {
712
701
  // src/components/Layer/index.tsx
713
702
  import {
714
703
  onCleanup as onCleanup3,
715
- createEffect as createEffect4,
704
+ createEffect as createEffect3,
716
705
  createMemo,
717
706
  createUniqueId as createUniqueId2
718
707
  } from "solid-js";
719
708
 
720
- // src/styles.ts
709
+ // src/components/Layer/styles.ts
721
710
  var baseStyle = [
722
711
  "id",
723
712
  "type",
@@ -781,7 +770,7 @@ var layoutStyles = [
781
770
  "text-writing-mode"
782
771
  ];
783
772
 
784
- // src/colors.ts
773
+ // src/components/Layer/colors.ts
785
774
  var probe;
786
775
  var toRgbString = (cssColor) => {
787
776
  probe ??= document.body.appendChild(document.createElement("div"));
@@ -826,7 +815,7 @@ var toRgbaComponents = (value) => {
826
815
  var PULSE_DEFAULTS = {
827
816
  property: "icon-halo-width",
828
817
  from: 0,
829
- to: 8,
818
+ to: 4,
830
819
  duration: 1500,
831
820
  waveform: "out"
832
821
  };
@@ -856,9 +845,16 @@ var diff = (newProps = {}, prevProps = {}) => {
856
845
  }, []);
857
846
  };
858
847
  var newKey = (key, type) => (key.startsWith(type) || key.startsWith("icon") || key.startsWith("text") ? "" : type + "-") + key.replace(/[A-Z]/g, (s) => "-" + s.toLowerCase());
859
- var resolveColor2 = (key, value) => key.endsWith("color") && typeof value === "string" ? resolveColor(value) : value;
848
+ var misplacedTopLevelProps = ["slot", "filter", "visible", "beforeId", "beforeType"];
849
+ var resolveColor2 = (key, value) => {
850
+ if (!key.endsWith("color")) return value;
851
+ if (Array.isArray(value)) return value.map((v) => resolveColor2(key, v));
852
+ return typeof value === "string" ? resolveColor(value) : value;
853
+ };
860
854
  var constantRef = /^@(.+)$/;
861
855
  var resolveConstant = (key, value, constants, debug) => {
856
+ if (Array.isArray(value))
857
+ return value.map((v) => resolveConstant(key, v, constants, debug));
862
858
  if (typeof value !== "string") return value;
863
859
  const match = value.match(constantRef);
864
860
  if (!match) return value;
@@ -879,6 +875,10 @@ var updateStyle = (oldStyle, constants = {}, debug = () => {
879
875
  Object.entries(oldStyle).forEach(([key, value]) => {
880
876
  if (baseStyle.includes(key)) style[key] = value;
881
877
  else {
878
+ if (misplacedTopLevelProps.includes(key))
879
+ debug(
880
+ `"${key}" is a <Layer> prop, not a style property \u2014 belongs outside "style", not inside it. Treating it as a paint/layout property instead.`
881
+ );
882
882
  const nk = newKey(key, oldStyle.type);
883
883
  layoutStyles.includes(nk) ? layout[nk] = resolveConstant(nk, value, constants, debug) : paint[nk] = resolvePaint(nk, value);
884
884
  }
@@ -910,7 +910,7 @@ var Layer = (props) => {
910
910
  ...updateStyle(props.style, ctx.constants, debug),
911
911
  id: layerId,
912
912
  source: sourceId,
913
- // `slot` is Mapbox Standard-Style-only — MapLibre has no equivalent (see docs/dev-notes.md)
913
+ // `slot` is Mapbox Standard-Style-only — MapLibre has no equivalent (see .claude/dev-notes.md)
914
914
  ...ctx.isMapLibre ? {} : { slot: props.slot || "" },
915
915
  metadata: {
916
916
  smg: { beforeType: props.beforeType, beforeId: props.beforeId }
@@ -925,13 +925,13 @@ var Layer = (props) => {
925
925
  if (props[item]) {
926
926
  const event = item.slice(2).toLowerCase();
927
927
  ctx.map.on(event, layerId, (evt) => {
928
- evt.clickOnLayer = true;
928
+ if (event === "click") evt.clickOnLayer = true;
929
929
  props[item](evt);
930
930
  ctx.map.debugEvents && debug(`Layer '${event}' event on '${layerId}':`, evt);
931
931
  });
932
932
  }
933
933
  });
934
- createEffect4((prev) => {
934
+ createEffect3((prev) => {
935
935
  ctx.themeVersion;
936
936
  const style = updateStyle(props.style, ctx.constants, debug);
937
937
  if (style === prev) return;
@@ -950,7 +950,7 @@ var Layer = (props) => {
950
950
  debug("Update Layer Style:", layerId);
951
951
  return style;
952
952
  }, updateStyle(props.style, ctx.constants, debug));
953
- createEffect4((prev) => {
953
+ createEffect3((prev) => {
954
954
  if (props.visible === prev) return;
955
955
  ctx.map.setLayoutProperty(
956
956
  layerId,
@@ -961,19 +961,20 @@ var Layer = (props) => {
961
961
  debug(`Update Visibility (${layerId}):`, props.visible.toString());
962
962
  return props.visible;
963
963
  }, props.visible);
964
- createEffect4((prev) => {
964
+ createEffect3((prev) => {
965
965
  if (getBeforeId() === prev) return prev;
966
966
  ctx.map.moveLayer(layerId, getBeforeId());
967
967
  debug(`Update Layer Z-Index (${layerId}):`, getBeforeId());
968
968
  return getBeforeId();
969
969
  }, getBeforeId());
970
- createEffect4(async () => {
971
- if (!props.filter) return;
972
- !ctx.map.isStyleLoaded() && await ctx.map.once("styledata");
973
- ctx.map.setFilter(layerId, props.filter);
970
+ createEffect3((prev) => {
971
+ if (props.filter === prev) return prev;
972
+ if (prev === void 0 && !props.filter) return prev;
973
+ ctx.map.setFilter(layerId, props.filter ?? null);
974
974
  debug(`Update Filter (${layerId}):`, props.filter);
975
- });
976
- createEffect4(async () => {
975
+ return props.filter;
976
+ }, void 0);
977
+ createEffect3(async () => {
977
978
  if (!props.featureState || props.featureState.id === null) return;
978
979
  !ctx.map.isStyleLoaded() && await ctx.map.once("styledata");
979
980
  ctx.map.removeFeatureState({
@@ -989,7 +990,7 @@ var Layer = (props) => {
989
990
  props.featureState.state
990
991
  );
991
992
  });
992
- createEffect4(() => {
993
+ createEffect3(() => {
993
994
  if (!props.pulse) return;
994
995
  const configs = props.pulse === true ? [{}] : Array.isArray(props.pulse) ? props.pulse : [props.pulse];
995
996
  const resolved = configs.map((config) => {
@@ -1010,6 +1011,14 @@ var Layer = (props) => {
1010
1011
  toRgba: isColor ? toRgbaComponents(b) : null
1011
1012
  };
1012
1013
  });
1014
+ resolved.forEach((cfg) => {
1015
+ ctx.map.setPaintProperty(
1016
+ layerId,
1017
+ `${cfg.property}-transition`,
1018
+ { duration: 0, delay: 0 },
1019
+ { validate: false }
1020
+ );
1021
+ });
1013
1022
  const start = performance.now();
1014
1023
  let frameId;
1015
1024
  const loop = (now) => {
@@ -1037,11 +1046,11 @@ import {
1037
1046
  createUniqueId as createUniqueId3,
1038
1047
  createSignal as createSignal2,
1039
1048
  onMount as onMount2,
1040
- createContext as createContext3,
1041
- useContext as useContext3
1049
+ createContext as createContext2,
1050
+ useContext as useContext2
1042
1051
  } from "solid-js";
1043
- var LayerContext = createContext3();
1044
- var useScene = () => useContext3(LayerContext);
1052
+ var LayerContext = createContext2();
1053
+ var useScene = () => useContext2(LayerContext);
1045
1054
  var Layer3D = (props) => {
1046
1055
  const [ctx] = useMapContext();
1047
1056
  const [scene, setScene] = createSignal2(null);
@@ -1181,10 +1190,10 @@ var Layer3D = (props) => {
1181
1190
  };
1182
1191
 
1183
1192
  // src/components/Atmosphere/index.tsx
1184
- import { onCleanup as onCleanup5, createEffect as createEffect5 } from "solid-js";
1193
+ import { onCleanup as onCleanup5, createEffect as createEffect4 } from "solid-js";
1185
1194
  var Atmosphere = (props) => {
1186
1195
  const [ctx] = useMapContext();
1187
- createEffect5(() => {
1196
+ createEffect4(() => {
1188
1197
  if (ctx.isMapLibre) ctx.map.setSky?.(props.style || {});
1189
1198
  else ctx.map.setFog(props.style || {});
1190
1199
  });
@@ -1200,7 +1209,7 @@ var Atmosphere = (props) => {
1200
1209
 
1201
1210
  // src/components/Terrain/index.tsx
1202
1211
  import {
1203
- createEffect as createEffect6,
1212
+ createEffect as createEffect5,
1204
1213
  createUniqueId as createUniqueId4,
1205
1214
  onCleanup as onCleanup6
1206
1215
  } from "solid-js";
@@ -1217,7 +1226,7 @@ var Terrain = (props) => {
1217
1226
  });
1218
1227
  ctx.map.sourceIdList.push(sourceId);
1219
1228
  }
1220
- createEffect6(() => {
1229
+ createEffect5(() => {
1221
1230
  ctx.map.setTerrain({
1222
1231
  exaggeration: props.exaggeration || 1,
1223
1232
  source: props?.source || sourceId
@@ -1228,13 +1237,13 @@ var Terrain = (props) => {
1228
1237
  };
1229
1238
 
1230
1239
  // src/components/Control/index.tsx
1231
- import { createSignal as createSignal3, createEffect as createEffect8, splitProps, untrack } from "solid-js";
1240
+ import { createSignal as createSignal3, createEffect as createEffect7, splitProps, untrack } from "solid-js";
1232
1241
 
1233
1242
  // src/lib/createMapControl.ts
1234
- import { createEffect as createEffect7, onCleanup as onCleanup7 } from "solid-js";
1243
+ import { createEffect as createEffect6, onCleanup as onCleanup7 } from "solid-js";
1235
1244
  var useControlPosition = (control, position) => {
1236
1245
  const [ctx] = useMapContext();
1237
- createEffect7(() => {
1246
+ createEffect6(() => {
1238
1247
  const c = control();
1239
1248
  const pos = position?.();
1240
1249
  if (!c) return;
@@ -1261,7 +1270,7 @@ var Control = (props) => {
1261
1270
  ["logo", ctx.mapLib.LogoControl],
1262
1271
  ["terrain", ctx.mapLib.TerrainControl]
1263
1272
  ]);
1264
- createEffect8(() => {
1273
+ createEffect7(() => {
1265
1274
  untrack(
1266
1275
  () => control() && ctx.map.hasControl(control()) && ctx.map.removeControl(control())
1267
1276
  );
@@ -1274,7 +1283,7 @@ var Control = (props) => {
1274
1283
  };
1275
1284
 
1276
1285
  // src/components/Marker/index.tsx
1277
- import { onCleanup as onCleanup8, createEffect as createEffect9, splitProps as splitProps2 } from "solid-js";
1286
+ import { onCleanup as onCleanup8, createEffect as createEffect8, splitProps as splitProps2 } from "solid-js";
1278
1287
  var Marker = (props) => {
1279
1288
  if (!props.lngLat) throw new Error("Marker - lngLat is required");
1280
1289
  const [update, create_popup, create_marker] = splitProps2(
@@ -1286,7 +1295,7 @@ var Marker = (props) => {
1286
1295
  let marker = null;
1287
1296
  let popup = null;
1288
1297
  const LNGLAT = update.lngLat;
1289
- createEffect9(() => {
1298
+ createEffect8(() => {
1290
1299
  if (!ctx.map) return;
1291
1300
  popup?.remove();
1292
1301
  popup = new ctx.mapLib.Popup({
@@ -1294,31 +1303,31 @@ var Marker = (props) => {
1294
1303
  focusAfterOpen: false,
1295
1304
  ...create_popup.popup
1296
1305
  }).on("open", () => create_popup.onOpen?.()).on("close", () => create_popup.onClose?.());
1297
- createEffect9(() => {
1306
+ createEffect8(() => {
1298
1307
  if (update.children === void 0) return;
1299
1308
  typeof update.children === "string" ? popup?.setHTML(update.children) : popup?.setDOMContent(update.children);
1300
1309
  marker?.setPopup(popup);
1301
1310
  });
1302
- createEffect9(
1311
+ createEffect8(
1303
1312
  () => update.showPopup !== popup?.isOpen() && marker?.togglePopup()
1304
1313
  );
1305
1314
  });
1306
- createEffect9(() => {
1315
+ createEffect8(() => {
1307
1316
  if (!ctx.map) return;
1308
1317
  marker?.remove();
1309
1318
  marker = new ctx.mapLib.Marker(create_marker.options).on("dragstart", () => create_marker.onDragStart?.()).on("dragend", () => create_marker.onDragEnd?.()).on("drag", () => create_marker.onDrag?.(marker?.getLngLat().toArray())).setPopup(popup).setLngLat(LNGLAT).addTo(ctx.map);
1310
- createEffect9(
1319
+ createEffect8(
1311
1320
  () => update.showPopup !== popup?.isOpen() && marker?.togglePopup()
1312
1321
  );
1313
1322
  });
1314
- createEffect9(() => marker?.setLngLat(update.lngLat));
1315
- createEffect9(() => marker?.setDraggable(update.draggable));
1323
+ createEffect8(() => marker?.setLngLat(update.lngLat));
1324
+ createEffect8(() => marker?.setDraggable(update.draggable));
1316
1325
  onCleanup8(() => marker?.remove());
1317
1326
  return null;
1318
1327
  };
1319
1328
 
1320
1329
  // src/components/Popup/index.tsx
1321
- import { onCleanup as onCleanup9, createEffect as createEffect10, splitProps as splitProps3 } from "solid-js";
1330
+ import { onCleanup as onCleanup9, createEffect as createEffect9, splitProps as splitProps3 } from "solid-js";
1322
1331
  var Popup = (props) => {
1323
1332
  if (!props.trackPointer && !props.lngLat)
1324
1333
  throw new Error("Popup - lngLat or trackPointer is required");
@@ -1329,7 +1338,7 @@ var Popup = (props) => {
1329
1338
  ]);
1330
1339
  const [ctx] = useMapContext();
1331
1340
  let popup;
1332
- createEffect10(() => {
1341
+ createEffect9(() => {
1333
1342
  if (!ctx.map) return;
1334
1343
  popup?.remove();
1335
1344
  popup = new ctx.mapLib.Popup({
@@ -1337,10 +1346,10 @@ var Popup = (props) => {
1337
1346
  focusAfterOpen: false,
1338
1347
  ...create.options
1339
1348
  }).on("open", () => create.onOpen?.()).on("close", () => create.onClose?.()).addTo(ctx.map);
1340
- createEffect10(
1349
+ createEffect9(
1341
1350
  () => update.trackPointer ? popup.trackPointer() : popup.setLngLat(update.lngLat)
1342
1351
  );
1343
- createEffect10(
1352
+ createEffect9(
1344
1353
  () => typeof update.children === "string" ? popup.setHTML(update.children) : popup.setDOMContent(update.children)
1345
1354
  );
1346
1355
  });
@@ -1352,7 +1361,7 @@ var Popup = (props) => {
1352
1361
  import {
1353
1362
  onCleanup as onCleanup10,
1354
1363
  createSignal as createSignal4,
1355
- createEffect as createEffect11,
1364
+ createEffect as createEffect10,
1356
1365
  untrack as untrack2
1357
1366
  } from "solid-js";
1358
1367
 
@@ -1364,12 +1373,12 @@ for (let i = 0; i < 256; i++) {
1364
1373
  ALPHA_TABLE[i] = d * Math.abs(d);
1365
1374
  }
1366
1375
  ALPHA_TABLE[255] = -INF;
1367
- function edt1d(grid, offset, stride, length3, f, v, z) {
1376
+ function edt1d(grid, offset, stride, length2, f, v, z) {
1368
1377
  v[0] = 0;
1369
1378
  z[0] = -INF;
1370
1379
  z[1] = INF;
1371
1380
  f[0] = grid[offset];
1372
- for (let q = 1, k = 0, s = 0; q < length3; q++) {
1381
+ for (let q = 1, k = 0, s = 0; q < length2; q++) {
1373
1382
  f[q] = grid[offset + q * stride];
1374
1383
  const q2 = q * q;
1375
1384
  do {
@@ -1381,7 +1390,7 @@ function edt1d(grid, offset, stride, length3, f, v, z) {
1381
1390
  z[k] = s;
1382
1391
  z[k + 1] = INF;
1383
1392
  }
1384
- for (let q = 0, k = 0; q < length3; q++) {
1393
+ for (let q = 0, k = 0; q < length2; q++) {
1385
1394
  while (z[k + 1] < q) k++;
1386
1395
  const r = v[k];
1387
1396
  const qr = q - r;
@@ -1461,34 +1470,51 @@ var PATTERN = {
1461
1470
  wave: { size: 20, path: "M0 5Q5 0 10 5T20 5M0 15Q5 10 10 15T20 15" }
1462
1471
  };
1463
1472
  var patternList = Object.keys(PATTERN);
1464
- var svg = (body) => `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64">${body}</svg>`;
1473
+ var svg = (path) => `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" stroke-linecap="round" stroke-linejoin="round">
1474
+ <path d="${path}" fill="#000" stroke="#000" stroke-width="3"/>
1475
+ </svg>`;
1465
1476
  var SYMBOL = {
1466
- square: svg('<rect x="8" y="8" width="48" height="48" fill="#000"/>'),
1467
- circle: svg('<circle cx="32" cy="32" r="28" fill="#000"/>'),
1468
- triangle: svg('<polygon points="32,6 60,56 4,56" fill="#000"/>'),
1469
- diamond: svg('<polygon points="32,4 60,32 32,60 4,32" fill="#000"/>'),
1470
- pentagon: svg('<polygon points="32,4 59,23 48,55 16,55 5,23" fill="#000"/>'),
1471
- hexagon: svg('<polygon points="32,4 56,18 56,46 32,60 8,46 8,18" fill="#000"/>'),
1477
+ square: svg("M3,3 L21,3 L21,21 L3,21 Z"),
1478
+ // Two semicircular arcs sharing one center/radius, traced in the same direction both times
1479
+ // (the standard "circle via two arcs" trick). The requested `1,1` radius is far smaller than
1480
+ // half the 16-unit chord between the two points, so per the SVG spec it's scaled up to the
1481
+ // minimum radius that can still connect them (8, i.e. exactly a semicircle each) — the circle
1482
+ // ends up centered on the chord's midpoint (12,11), not on the literal "1".
1483
+ circle: svg("M 12 4 A 1 1 0 0 0 12 20 A 1 1 0 0 0 12 4 Z"),
1484
+ triangle: svg("M 12 2 L 22 19 H 2 Z"),
1485
+ diamond: svg("M 12 1 L 19 12 L 12 23 L 5 12 Z"),
1486
+ pentagon: svg("M12,3 L21,9 L17,19 L7,19 L3,9 Z"),
1487
+ hexagon: svg("M12,3 L20,7.5 L20,16.5 L12,21 L4,16.5 L4,7.5 Z"),
1472
1488
  // A square with corners cut at 2/7 of its side, the standard construction for a regular
1473
1489
  // octagon (stop-sign proportions) without resorting to trig.
1474
- octagon: svg(
1475
- '<polygon points="20,4 44,4 60,20 60,44 44,60 20,60 4,44 4,20" fill="#000"/>'
1476
- ),
1477
- cross: svg(
1478
- '<polygon points="20,4 44,4 44,20 60,20 60,44 44,44 44,60 20,60 20,44 4,44 4,20 20,20" fill="#000"/>'
1479
- ),
1490
+ octagon: svg("M 8 3 Q 12 3.3 16 3 Q 18.3 5.7 21 8 Q 20.7 12 21 16 Q 18.3 18.3 16 21 Q 12 20.7 8 21 Q 5.8 18.2 3 16 Q 3.3 12 3 8 Q 5.7 5.7 8 3 Z"),
1491
+ cross: svg("M 10.5 3 h 3 v 7.5 h 7.5 v 3 h -7.5 v 7.5 h -3 v -7.5 h -7.5 v -3 h 7.5 Z"),
1480
1492
  // The same 12-point "+" as `cross` above, rotated 45° about the center.
1481
- x: svg(
1482
- '<polygon points="43,4 60,21 49,32 60,43 43,60 32,49 21,60 4,43 15,32 4,21 21,4 32,15" fill="#000"/>'
1483
- ),
1484
- // A regular 5-pointed star: outer vertices every 72° (radius 30) alternating with inner
1485
- // vertices every 72° offset by 36° (radius ~11.5, the usual ratio for a balanced star).
1486
- star: svg(
1487
- '<polygon points="32,2 39,23 61,23 43,36 50,56 32,44 14,56 21,36 4,23 25,23" fill="#000"/>'
1488
- )
1493
+ x: svg("M 18 4 L 20 6 L 14 12 L 20 18 L 18 20 L 12 14 L 6 20 L 4 18 L 10 12 L 4 6 L 6 4 L 12 10 Z"),
1494
+ // A regular 5-pointed star: outer vertices every 72° alternating with inner vertices every
1495
+ // 72° offset by 36° (inner radius ~40% of the outer radius, the usual ratio for a balanced star).
1496
+ star: svg("M12,3 L14,9 L20.5,9 L15.5,13 L17.5,19.5 L12,15.5 L6.5,19.5 L8.5,13 L3.5,9 L10,9 Z"),
1497
+ // Two circular lobes (centers 8.5,8 / 15.5,8, radius 4.5 apart enough to overlap) joined by
1498
+ // straight tangent lines down to a bottom point. The notch between the lobes is the two
1499
+ // circles' actual intersection point (computed, not eyeballed), so both arcs land on it
1500
+ // exactly with no seam.
1501
+ heart: svg("M 12 21 L 3 11 A 4.5 4.5 0 1 1 11 8 L 13 8 A 4.5 4.5 0 1 1 21 11 Z"),
1502
+ // A map-pin/teardrop: a circle (center 12,10, r6) with two lines tangent to it converging on a
1503
+ // point below, so the straight edges meet the round top without a kink — the tangent points
1504
+ // and angles come from `acos(r / distance-to-point)`, not eyeballing.
1505
+ pin: svg("M 12 21 L 7 11 A 6 6 0 0 1 12 2 A 6 6 0 0 1 17 11 Z"),
1506
+ // The same tangent-circle construction as `pin`, just with the circle bigger relative to how
1507
+ // far below it the point sits (r6/d11 there vs r7.5/d10.5 here) — a shorter, wider point on a
1508
+ // rounder body: "a circle with one pointy edge" rather than a full elongated marker.
1509
+ drop: svg("M 4 21 V 12 A 7.5 7.5 0 0 1 12 4 A 7.5 7.5 0 0 1 13 21 Z"),
1510
+ // A thick chevron/bracket built as a filled ribbon, not a stroked open line: the outer and
1511
+ // inner edges of a constant-width "V", offset perpendicular to each arm and mitered where the
1512
+ // arms meet (both at the outer point and the inner notch). Has to be a closed silhouette like
1513
+ // every other symbol here, since `sdf` only encodes a filled alpha shape, not a stroke.
1514
+ chevron: svg("M 8 4 L 14 12 L 8 20 H 5 L 11 12 L 5 4 Z")
1489
1515
  };
1490
1516
  var symbolList = Object.keys(SYMBOL);
1491
- var wrapSymbolPath = (d) => svg(`<path d="${d}" fill="#000"/>`);
1517
+ var wrapSymbolPath = (d) => svg(d);
1492
1518
 
1493
1519
  // src/components/Image/index.tsx
1494
1520
  var MGL_Image = (props) => {
@@ -1509,7 +1535,7 @@ var MGL_Image = (props) => {
1509
1535
  ctx.map?.hasImage(props.id) && ctx.map?.removeImage(props.id);
1510
1536
  debug("Remove Image:", props.id);
1511
1537
  });
1512
- createEffect11(() => {
1538
+ createEffect10(() => {
1513
1539
  if (!props.id) throw new Error("Image - ID is required");
1514
1540
  if (!props.source && !props.pattern && !props.symbol)
1515
1541
  throw new Error("Image - Image, Pattern or Symbol is required");
@@ -1557,10 +1583,11 @@ var MGL_Image = (props) => {
1557
1583
  const img = new Image();
1558
1584
  img.crossOrigin = "Anonymous";
1559
1585
  img.onload = () => {
1560
- const floorScale = Math.max(1, 50 / Math.min(img.width, img.height));
1586
+ const minAxis = Math.min(img.width, img.height);
1587
+ const floorScale = minAxis > 0 ? Math.max(1, 50 / minAxis) : 1;
1561
1588
  const pixelRatio = props.options?.pixelRatio ?? Math.max(1, Math.round(window.devicePixelRatio || 1));
1562
1589
  const scale = floorScale * pixelRatio;
1563
- const padding = sdfOpts ? sdfPadding(sdfOpts) * pixelRatio : 0;
1590
+ const padding = sdfOpts ? sdfPadding(sdfOpts) * scale : 0;
1564
1591
  const drawWidth = Math.round(img.width * scale);
1565
1592
  const drawHeight = Math.round(img.height * scale);
1566
1593
  const canvas = document.createElement("canvas");
@@ -1572,7 +1599,7 @@ var MGL_Image = (props) => {
1572
1599
  const imageData2 = ctx2.getImageData(0, 0, canvas.width, canvas.height);
1573
1600
  return callback(
1574
1601
  sdfOpts ? toSDF(imageData2, sdfOpts) : imageData2,
1575
- pixelRatio
1602
+ scale
1576
1603
  );
1577
1604
  };
1578
1605
  img.onerror = (event) => console.error(`[MapGL] Image "${props.id}" failed to load:`, event);
@@ -1625,7 +1652,7 @@ var MGL_Image = (props) => {
1625
1652
  };
1626
1653
 
1627
1654
  // src/components/Camera/index.tsx
1628
- import { createEffect as createEffect12, onCleanup as onCleanup11, createSignal as createSignal5 } from "solid-js";
1655
+ import { createEffect as createEffect11, onCleanup as onCleanup11, createSignal as createSignal5 } from "solid-js";
1629
1656
  var lerp = (a, b, t) => a.map((_, idx) => (1 - t) * a[idx] + t * b[idx]);
1630
1657
  var slerp = (a, b, t) => {
1631
1658
  const dotProduct = a.map((_, idx) => a[idx] * b[idx]).reduce((m, n) => m + n);
@@ -1672,7 +1699,7 @@ var Camera = (props) => {
1672
1699
  isReverse = !isReverse;
1673
1700
  animationTime = isReverse ? animationTime - 1e-3 : animationTime + 1e-3;
1674
1701
  };
1675
- createEffect12(() => {
1702
+ createEffect11(() => {
1676
1703
  props.translate && window.requestAnimationFrame(frame);
1677
1704
  });
1678
1705
  const options = { duration: 1e3, easing: (n) => n };
@@ -1707,7 +1734,7 @@ var Camera = (props) => {
1707
1734
  const onEnd = () => props.rotateGlobe ? rotateGlobe() : rotateViewport();
1708
1735
  ctx.map.on("moveend", onEnd).on("dragend", onEnd);
1709
1736
  let originalCenter;
1710
- createEffect12(() => {
1737
+ createEffect11(() => {
1711
1738
  if (props.rotateGlobe == void 0) return;
1712
1739
  if (props.rotateGlobe) {
1713
1740
  originalCenter = ctx.map.getCenter();
@@ -1716,7 +1743,7 @@ var Camera = (props) => {
1716
1743
  props.resetWhenStopped ? ctx.map.stop().easeTo({ center: originalCenter }) : ctx.map.stop();
1717
1744
  }
1718
1745
  });
1719
- createEffect12(() => {
1746
+ createEffect11(() => {
1720
1747
  if (props.rotateViewport == void 0) return;
1721
1748
  props.rotateViewport ? rotateViewport() : props.resetWhenStopped ? ctx.map.stop().resetNorthPitch() : ctx.map.stop();
1722
1749
  });
@@ -1725,10 +1752,10 @@ var Camera = (props) => {
1725
1752
  };
1726
1753
 
1727
1754
  // src/components/Light/index.tsx
1728
- import { onCleanup as onCleanup12, createEffect as createEffect13 } from "solid-js";
1755
+ import { onCleanup as onCleanup12, createEffect as createEffect12 } from "solid-js";
1729
1756
  var Light = (props) => {
1730
1757
  const [ctx] = useMapContext();
1731
- createEffect13(() => ctx.map.setLight(props.style || {}));
1758
+ createEffect12(() => ctx.map.setLight(props.style || {}));
1732
1759
  onCleanup12(() => ctx.map?.setLight(null));
1733
1760
  return null;
1734
1761
  };
@@ -1764,11 +1791,105 @@ MultiPointMode.toDisplayFeatures = function(state, geojson, display) {
1764
1791
  };
1765
1792
  var multi_point_default = MultiPointMode;
1766
1793
 
1794
+ // src/components/Draw/modes/geo.ts
1795
+ var EARTH_RADIUS_KM = 6371.0088;
1796
+ var KM_PER_MILE = 1.609344;
1797
+ var EARTH_RADIUS_M = 6378137;
1798
+ function toRadians(deg) {
1799
+ return deg * Math.PI / 180;
1800
+ }
1801
+ function toDegrees(rad) {
1802
+ return rad * 180 / Math.PI;
1803
+ }
1804
+ function distance(from, to) {
1805
+ const dLat = toRadians(to[1] - from[1]);
1806
+ const dLng = toRadians(to[0] - from[0]);
1807
+ const lat1 = toRadians(from[1]);
1808
+ const lat2 = toRadians(to[1]);
1809
+ const a = Math.sin(dLat / 2) ** 2 + Math.cos(lat1) * Math.cos(lat2) * Math.sin(dLng / 2) ** 2;
1810
+ return EARTH_RADIUS_KM * 2 * Math.asin(Math.sqrt(a));
1811
+ }
1812
+ function length(coordinates, units = "kilometers") {
1813
+ let total = 0;
1814
+ for (let i = 1; i < coordinates.length; i++) {
1815
+ total += distance(coordinates[i - 1], coordinates[i]);
1816
+ }
1817
+ return units === "miles" ? total / KM_PER_MILE : total;
1818
+ }
1819
+ function midpoint(from, to) {
1820
+ const lat1 = toRadians(from[1]);
1821
+ const lon1 = toRadians(from[0]);
1822
+ const lat2 = toRadians(to[1]);
1823
+ const dLon = toRadians(to[0] - from[0]);
1824
+ const bx = Math.cos(lat2) * Math.cos(dLon);
1825
+ const by = Math.cos(lat2) * Math.sin(dLon);
1826
+ const lat3 = Math.atan2(
1827
+ Math.sin(lat1) + Math.sin(lat2),
1828
+ Math.sqrt((Math.cos(lat1) + bx) ** 2 + by ** 2)
1829
+ );
1830
+ const lon3 = lon1 + Math.atan2(by, Math.cos(lat1) + bx);
1831
+ return [toDegrees(lon3), toDegrees(lat3)];
1832
+ }
1833
+ function ringArea(ring) {
1834
+ const n = ring.length;
1835
+ if (n <= 2) return 0;
1836
+ let total = 0;
1837
+ for (let i = 0; i < n; i++) {
1838
+ let lower;
1839
+ let middle;
1840
+ let upper;
1841
+ if (i === n - 2) {
1842
+ lower = n - 2;
1843
+ middle = n - 1;
1844
+ upper = 0;
1845
+ } else if (i === n - 1) {
1846
+ lower = n - 1;
1847
+ middle = 0;
1848
+ upper = 1;
1849
+ } else {
1850
+ lower = i;
1851
+ middle = i + 1;
1852
+ upper = i + 2;
1853
+ }
1854
+ total += (toRadians(ring[upper][0]) - toRadians(ring[lower][0])) * Math.sin(toRadians(ring[middle][1]));
1855
+ }
1856
+ return total * EARTH_RADIUS_M * EARTH_RADIUS_M / 2;
1857
+ }
1858
+ function area(rings) {
1859
+ return rings.reduce((total, ring, i) => {
1860
+ const ringTotal = Math.abs(ringArea(ring));
1861
+ return i === 0 ? total + ringTotal : total - ringTotal;
1862
+ }, 0);
1863
+ }
1864
+ function centerOfMass(rings) {
1865
+ const ring = rings[0];
1866
+ let meanX = 0;
1867
+ let meanY = 0;
1868
+ for (const [x, y] of ring) {
1869
+ meanX += x;
1870
+ meanY += y;
1871
+ }
1872
+ meanX /= ring.length;
1873
+ meanY /= ring.length;
1874
+ let xSum = 0;
1875
+ let ySum = 0;
1876
+ let areaSum = 0;
1877
+ for (let i = 0; i < ring.length - 1; i++) {
1878
+ const x1 = ring[i][0] - meanX;
1879
+ const y1 = ring[i][1] - meanY;
1880
+ const x2 = ring[i + 1][0] - meanX;
1881
+ const y2 = ring[i + 1][1] - meanY;
1882
+ const cross = x1 * y2 - x2 * y1;
1883
+ xSum += (x1 + x2) * cross;
1884
+ ySum += (y1 + y2) * cross;
1885
+ areaSum += cross;
1886
+ }
1887
+ if (areaSum === 0) return [meanX, meanY];
1888
+ const factor = 1 / (3 * areaSum);
1889
+ return [meanX + xSum * factor, meanY + ySum * factor];
1890
+ }
1891
+
1767
1892
  // src/components/Draw/modes/measurements.ts
1768
- import length from "@turf/length";
1769
- import area from "@turf/area";
1770
- import midpoint from "@turf/midpoint";
1771
- import { centerOfMass } from "@turf/center-of-mass";
1772
1893
  var getCoords = (coords) => {
1773
1894
  return new Intl.NumberFormat(void 0, {
1774
1895
  maximumFractionDigits: 5
@@ -1778,17 +1899,8 @@ var getCoords = (coords) => {
1778
1899
  };
1779
1900
  var getLength = (coordinates, meta) => {
1780
1901
  const lengthValue = length(
1781
- {
1782
- type: "Feature",
1783
- properties: {},
1784
- geometry: {
1785
- type: "LineString",
1786
- coordinates
1787
- }
1788
- },
1789
- {
1790
- units: window.navigator.language === "en-US" ? "miles" : "kilometers"
1791
- }
1902
+ coordinates,
1903
+ window.navigator.language === "en-US" ? "miles" : "kilometers"
1792
1904
  );
1793
1905
  const label = window.navigator.language === "en-US" ? new Intl.NumberFormat(void 0, {
1794
1906
  style: "unit",
@@ -1808,19 +1920,12 @@ var getLength = (coordinates, meta) => {
1808
1920
  },
1809
1921
  geometry: {
1810
1922
  type: "Point",
1811
- coordinates: midpoint(coordinates[0], coordinates[1]).geometry.coordinates
1923
+ coordinates: midpoint(coordinates[0], coordinates[1])
1812
1924
  }
1813
1925
  };
1814
1926
  };
1815
1927
  var getArea = (coordinates, meta) => {
1816
- const areaValue = area({
1817
- type: "Feature",
1818
- properties: {},
1819
- geometry: {
1820
- type: "Polygon",
1821
- coordinates
1822
- }
1823
- });
1928
+ const areaValue = area(coordinates);
1824
1929
  const areaLabel = window.navigator.language === "en-US" ? new Intl.NumberFormat(void 0, {
1825
1930
  style: "unit",
1826
1931
  maximumFractionDigits: 2,
@@ -1839,10 +1944,10 @@ var getArea = (coordinates, meta) => {
1839
1944
  value: areaLabel,
1840
1945
  ...meta
1841
1946
  },
1842
- geometry: centerOfMass({
1843
- type: "Polygon",
1844
- coordinates
1845
- }).geometry
1947
+ geometry: {
1948
+ type: "Point",
1949
+ coordinates: centerOfMass(coordinates)
1950
+ }
1846
1951
  };
1847
1952
  };
1848
1953
 
@@ -1936,7 +2041,6 @@ var polygon_default = (lib) => {
1936
2041
  };
1937
2042
 
1938
2043
  // src/components/Draw/modes/radius.ts
1939
- import length2 from "@turf/length";
1940
2044
  function createVertex(parentId, coordinates, path, selected) {
1941
2045
  return {
1942
2046
  type: "Feature",
@@ -2019,7 +2123,7 @@ var RadiusMode = (lib) => ({
2019
2123
  state.line.removeCoordinate("0");
2020
2124
  if (state.line.isValid()) {
2021
2125
  const lineGeoJson = state.line.toGeoJSON();
2022
- const radius = (length2(lineGeoJson) * 1e3).toFixed(1);
2126
+ const radius = (length(lineGeoJson.geometry.coordinates) * 1e3).toFixed(1);
2023
2127
  const center = lineGeoJson.geometry.coordinates[0];
2024
2128
  this.deleteFeature([state.line.id], { silent: true });
2025
2129
  const point = this.newFeature({
@@ -2059,7 +2163,7 @@ var RadiusMode = (lib) => ({
2059
2163
  display(
2060
2164
  createGeoJSONCircle(
2061
2165
  geojson.geometry.coordinates[0],
2062
- length2(geojson),
2166
+ length(geojson.geometry.coordinates),
2063
2167
  state.line.id
2064
2168
  )
2065
2169
  );
@@ -2685,7 +2789,7 @@ var Draw = (props) => {
2685
2789
  };
2686
2790
 
2687
2791
  // src/components/DeckOverlay/index.tsx
2688
- import { createEffect as createEffect14 } from "solid-js";
2792
+ import { createEffect as createEffect13 } from "solid-js";
2689
2793
  var DeckOverlay = (props) => {
2690
2794
  const [ctx] = useMapContext();
2691
2795
  let overlay;
@@ -2694,7 +2798,7 @@ var DeckOverlay = (props) => {
2694
2798
  return overlay;
2695
2799
  };
2696
2800
  useControlPosition(control);
2697
- createEffect14(() => overlay?.setProps(props.props || {}));
2801
+ createEffect13(() => overlay?.setProps(props.props || {}));
2698
2802
  return null;
2699
2803
  };
2700
2804
  export {