@elabs-ai/components-maps 4.2.0 → 5.1.0

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.
Files changed (291) hide show
  1. package/README.md +1 -1
  2. package/dist/chunk-2FPB53NG.js +36 -0
  3. package/dist/chunk-2FPB53NG.js.map +1 -0
  4. package/dist/chunk-2VVJRT66.js +37 -0
  5. package/dist/chunk-2VVJRT66.js.map +1 -0
  6. package/dist/chunk-3HXFONRP.js +2 -0
  7. package/dist/chunk-3HXFONRP.js.map +1 -0
  8. package/dist/chunk-3SJN3IYT.js +2 -0
  9. package/dist/chunk-3SJN3IYT.js.map +1 -0
  10. package/dist/chunk-4DANBD5B.js +55 -0
  11. package/dist/chunk-4DANBD5B.js.map +1 -0
  12. package/dist/chunk-5PDVG53B.js +2 -0
  13. package/dist/chunk-5PDVG53B.js.map +1 -0
  14. package/dist/chunk-643R7IJC.js +2 -0
  15. package/dist/chunk-643R7IJC.js.map +1 -0
  16. package/dist/chunk-B3ZDBQ6I.js +164 -0
  17. package/dist/chunk-B3ZDBQ6I.js.map +1 -0
  18. package/dist/chunk-BGCE3RR5.js +35 -0
  19. package/dist/chunk-BGCE3RR5.js.map +1 -0
  20. package/dist/chunk-C4VI37TD.js +485 -0
  21. package/dist/chunk-C4VI37TD.js.map +1 -0
  22. package/dist/chunk-CJJT6AEI.js +179 -0
  23. package/dist/chunk-CJJT6AEI.js.map +1 -0
  24. package/dist/chunk-D2RCPTRO.js +2 -0
  25. package/dist/chunk-D2RCPTRO.js.map +1 -0
  26. package/dist/chunk-DTV7JZVN.js +2 -0
  27. package/dist/chunk-DTV7JZVN.js.map +1 -0
  28. package/dist/chunk-E65Z3MSV.js +80 -0
  29. package/dist/chunk-E65Z3MSV.js.map +1 -0
  30. package/dist/chunk-E7VPNINZ.js +70 -0
  31. package/dist/chunk-E7VPNINZ.js.map +1 -0
  32. package/dist/chunk-FHV5IA6N.js +100 -0
  33. package/dist/chunk-FHV5IA6N.js.map +1 -0
  34. package/dist/chunk-FQ6V7BFZ.js +347 -0
  35. package/dist/chunk-FQ6V7BFZ.js.map +1 -0
  36. package/dist/chunk-G7JDXDJN.js +19 -0
  37. package/dist/chunk-G7JDXDJN.js.map +1 -0
  38. package/dist/chunk-GWULZOMW.js +21 -0
  39. package/dist/chunk-GWULZOMW.js.map +1 -0
  40. package/dist/chunk-GYDTTAVD.js +120 -0
  41. package/dist/chunk-GYDTTAVD.js.map +1 -0
  42. package/dist/chunk-HCOBWIM4.js +48 -0
  43. package/dist/chunk-HCOBWIM4.js.map +1 -0
  44. package/dist/chunk-IAHK5MVT.js +2 -0
  45. package/dist/chunk-IAHK5MVT.js.map +1 -0
  46. package/dist/chunk-JGJ6442I.js +235 -0
  47. package/dist/chunk-JGJ6442I.js.map +1 -0
  48. package/dist/chunk-JYFERXZT.js +18 -0
  49. package/dist/chunk-JYFERXZT.js.map +1 -0
  50. package/dist/chunk-LU2UEKFM.js +53 -0
  51. package/dist/chunk-LU2UEKFM.js.map +1 -0
  52. package/dist/chunk-LVYM6C5C.js +2 -0
  53. package/dist/chunk-LVYM6C5C.js.map +1 -0
  54. package/dist/chunk-MIMDP3EU.js +104 -0
  55. package/dist/chunk-MIMDP3EU.js.map +1 -0
  56. package/dist/chunk-NNBURJHY.js +2 -0
  57. package/dist/chunk-NNBURJHY.js.map +1 -0
  58. package/dist/chunk-NPUC3V37.js +2 -0
  59. package/dist/chunk-NPUC3V37.js.map +1 -0
  60. package/dist/chunk-OEVVNPN3.js +201 -0
  61. package/dist/chunk-OEVVNPN3.js.map +1 -0
  62. package/dist/chunk-PF3R2BXM.js +200 -0
  63. package/dist/chunk-PF3R2BXM.js.map +1 -0
  64. package/dist/chunk-Q2I5YODW.js +2 -0
  65. package/dist/chunk-Q2I5YODW.js.map +1 -0
  66. package/dist/chunk-QDWWP3N7.js +247 -0
  67. package/dist/chunk-QDWWP3N7.js.map +1 -0
  68. package/dist/chunk-QU33KPMP.js +2 -0
  69. package/dist/chunk-QU33KPMP.js.map +1 -0
  70. package/dist/chunk-RK4BUMHS.js +2 -0
  71. package/dist/chunk-RK4BUMHS.js.map +1 -0
  72. package/dist/chunk-RNSLG64F.js +26 -0
  73. package/dist/chunk-RNSLG64F.js.map +1 -0
  74. package/dist/chunk-RV673TB4.js +68 -0
  75. package/dist/chunk-RV673TB4.js.map +1 -0
  76. package/dist/chunk-S7N2WMVT.js +180 -0
  77. package/dist/chunk-S7N2WMVT.js.map +1 -0
  78. package/dist/chunk-T3Z6TCDD.js +2 -0
  79. package/dist/chunk-T3Z6TCDD.js.map +1 -0
  80. package/dist/chunk-T4TJTVVA.js +105 -0
  81. package/dist/chunk-T4TJTVVA.js.map +1 -0
  82. package/dist/chunk-UMOYRCDX.js +103 -0
  83. package/dist/chunk-UMOYRCDX.js.map +1 -0
  84. package/dist/chunk-V2REM6UT.js +185 -0
  85. package/dist/chunk-V2REM6UT.js.map +1 -0
  86. package/dist/chunk-VFBRFGID.js +89 -0
  87. package/dist/chunk-VFBRFGID.js.map +1 -0
  88. package/dist/chunk-W76NLFER.js +103 -0
  89. package/dist/chunk-W76NLFER.js.map +1 -0
  90. package/dist/chunk-WNU4IOGL.js +116 -0
  91. package/dist/chunk-WNU4IOGL.js.map +1 -0
  92. package/dist/chunk-WS4Z7ENS.js +494 -0
  93. package/dist/chunk-WS4Z7ENS.js.map +1 -0
  94. package/dist/chunk-XQT7YLJY.js +497 -0
  95. package/dist/chunk-XQT7YLJY.js.map +1 -0
  96. package/dist/chunk-Y44MEKJV.js +21 -0
  97. package/dist/chunk-Y44MEKJV.js.map +1 -0
  98. package/dist/chunk-Z4EPSOB4.js +53 -0
  99. package/dist/chunk-Z4EPSOB4.js.map +1 -0
  100. package/dist/chunk-Z5OPDBDC.js +2 -0
  101. package/dist/chunk-Z5OPDBDC.js.map +1 -0
  102. package/dist/index.d.ts +1241 -46
  103. package/dist/index.js +189 -1471
  104. package/dist/index.js.map +1 -1
  105. package/dist/lib/arc-math.js +8 -0
  106. package/dist/lib/arc-math.js.map +1 -0
  107. package/dist/lib/map-position.js +11 -0
  108. package/dist/lib/map-position.js.map +1 -0
  109. package/dist/lib/merge-hover-paint.js +10 -0
  110. package/dist/lib/merge-hover-paint.js.map +1 -0
  111. package/dist/lib/plan-crs.js +14 -0
  112. package/dist/lib/plan-crs.js.map +1 -0
  113. package/dist/lib/plan-patterns.js +14 -0
  114. package/dist/lib/plan-patterns.js.map +1 -0
  115. package/dist/lib/plan-regions.js +18 -0
  116. package/dist/lib/plan-regions.js.map +1 -0
  117. package/dist/lib/plan-status.js +14 -0
  118. package/dist/lib/plan-status.js.map +1 -0
  119. package/dist/lib/route-arrow.js +12 -0
  120. package/dist/lib/route-arrow.js.map +1 -0
  121. package/dist/lib/use-map-breakpoint.js +33 -0
  122. package/dist/lib/use-map-breakpoint.js.map +1 -0
  123. package/dist/lib/use-plan-projection.js +9 -0
  124. package/dist/lib/use-plan-projection.js.map +1 -0
  125. package/dist/lib/use-token-color.js +10 -0
  126. package/dist/lib/use-token-color.js.map +1 -0
  127. package/dist/lib/warn-once.js +10 -0
  128. package/dist/lib/warn-once.js.map +1 -0
  129. package/dist/map-annotation/anchor.js +14 -0
  130. package/dist/map-annotation/anchor.js.map +1 -0
  131. package/dist/map-annotation/index.js +21 -0
  132. package/dist/map-annotation/index.js.map +1 -0
  133. package/dist/map-annotation/map-annotation.js +18 -0
  134. package/dist/map-annotation/map-annotation.js.map +1 -0
  135. package/dist/map-arc/index.js +16 -0
  136. package/dist/map-arc/index.js.map +1 -0
  137. package/dist/map-arc/map-arc.js +13 -0
  138. package/dist/map-arc/map-arc.js.map +1 -0
  139. package/dist/map-canvas/index.css +11 -0
  140. package/dist/map-canvas/index.css.map +1 -0
  141. package/dist/map-canvas/index.js +20 -0
  142. package/dist/map-canvas/index.js.map +1 -0
  143. package/dist/map-canvas/map-canvas.css +11 -0
  144. package/dist/map-canvas/map-canvas.css.map +1 -0
  145. package/dist/map-canvas/map-canvas.js +17 -0
  146. package/dist/map-canvas/map-canvas.js.map +1 -0
  147. package/dist/map-canvas/map-context.js +11 -0
  148. package/dist/map-canvas/map-context.js.map +1 -0
  149. package/dist/map-canvas/use-resolved-basemap-theme.js +9 -0
  150. package/dist/map-canvas/use-resolved-basemap-theme.js.map +1 -0
  151. package/dist/map-cluster-layer/index.js +12 -0
  152. package/dist/map-cluster-layer/index.js.map +1 -0
  153. package/dist/map-cluster-layer/map-cluster-layer.js +12 -0
  154. package/dist/map-cluster-layer/map-cluster-layer.js.map +1 -0
  155. package/dist/map-controls/index.js +11 -0
  156. package/dist/map-controls/index.js.map +1 -0
  157. package/dist/map-controls/map-controls.js +11 -0
  158. package/dist/map-controls/map-controls.js.map +1 -0
  159. package/dist/map-geojson/index.js +13 -0
  160. package/dist/map-geojson/index.js.map +1 -0
  161. package/dist/map-geojson/map-geojson.js +13 -0
  162. package/dist/map-geojson/map-geojson.js.map +1 -0
  163. package/dist/map-inset/index.css +11 -0
  164. package/dist/map-inset/index.css.map +1 -0
  165. package/dist/map-inset/index.js +20 -0
  166. package/dist/map-inset/index.js.map +1 -0
  167. package/dist/map-inset/map-inset.css +11 -0
  168. package/dist/map-inset/map-inset.css.map +1 -0
  169. package/dist/map-inset/map-inset.js +20 -0
  170. package/dist/map-inset/map-inset.js.map +1 -0
  171. package/dist/map-legend/index.js +14 -0
  172. package/dist/map-legend/index.js.map +1 -0
  173. package/dist/map-legend/map-corner.js +10 -0
  174. package/dist/map-legend/map-corner.js.map +1 -0
  175. package/dist/map-legend/map-legend.js +11 -0
  176. package/dist/map-legend/map-legend.js.map +1 -0
  177. package/dist/map-marker/index.js +22 -0
  178. package/dist/map-marker/index.js.map +1 -0
  179. package/dist/map-marker/map-marker.js +22 -0
  180. package/dist/map-marker/map-marker.js.map +1 -0
  181. package/dist/map-north-arrow/index.js +11 -0
  182. package/dist/map-north-arrow/index.js.map +1 -0
  183. package/dist/map-north-arrow/map-north-arrow.js +11 -0
  184. package/dist/map-north-arrow/map-north-arrow.js.map +1 -0
  185. package/dist/map-plan/index.js +30 -0
  186. package/dist/map-plan/index.js.map +1 -0
  187. package/dist/map-plan/map-plan-legend.js +10 -0
  188. package/dist/map-plan/map-plan-legend.js.map +1 -0
  189. package/dist/map-plan/map-plan-overlay.js +13 -0
  190. package/dist/map-plan/map-plan-overlay.js.map +1 -0
  191. package/dist/map-plan/map-plan-status.js +9 -0
  192. package/dist/map-plan/map-plan-status.js.map +1 -0
  193. package/dist/map-plan/map-plan-table.js +10 -0
  194. package/dist/map-plan/map-plan-table.js.map +1 -0
  195. package/dist/map-plan/use-plan-selection.js +9 -0
  196. package/dist/map-plan/use-plan-selection.js.map +1 -0
  197. package/dist/map-plan-image/index.js +11 -0
  198. package/dist/map-plan-image/index.js.map +1 -0
  199. package/dist/map-plan-image/map-plan-image.js +11 -0
  200. package/dist/map-plan-image/map-plan-image.js.map +1 -0
  201. package/dist/map-popup/index.js +12 -0
  202. package/dist/map-popup/index.js.map +1 -0
  203. package/dist/map-popup/map-popup.js +12 -0
  204. package/dist/map-popup/map-popup.js.map +1 -0
  205. package/dist/map-route/index.js +12 -0
  206. package/dist/map-route/index.js.map +1 -0
  207. package/dist/map-route/map-route.js +12 -0
  208. package/dist/map-route/map-route.js.map +1 -0
  209. package/dist/map-scale-bar/index.js +18 -0
  210. package/dist/map-scale-bar/index.js.map +1 -0
  211. package/dist/map-scale-bar/map-scale-bar.js +18 -0
  212. package/dist/map-scale-bar/map-scale-bar.js.map +1 -0
  213. package/package.json +5 -5
  214. package/src/index.ts +83 -0
  215. package/src/lib/arc-math.test.ts +19 -0
  216. package/src/lib/arc-math.ts +6 -1
  217. package/src/lib/map-position.ts +77 -0
  218. package/src/lib/merge-hover-paint.ts +44 -13
  219. package/src/lib/plan-crs.parity.test.ts +39 -0
  220. package/src/lib/plan-crs.test.ts +248 -0
  221. package/src/lib/plan-crs.ts +252 -0
  222. package/src/lib/plan-patterns.test.ts +255 -0
  223. package/src/lib/plan-patterns.ts +160 -0
  224. package/src/lib/plan-regions.test.ts +186 -0
  225. package/src/lib/plan-regions.ts +209 -0
  226. package/src/lib/plan-status.test.ts +87 -0
  227. package/src/lib/plan-status.ts +147 -0
  228. package/src/lib/route-arrow.test.ts +88 -0
  229. package/src/lib/route-arrow.ts +59 -0
  230. package/src/lib/use-map-breakpoint.test.ts +83 -0
  231. package/src/lib/use-map-breakpoint.ts +238 -0
  232. package/src/lib/use-plan-projection.ts +157 -0
  233. package/src/lib/warn-once.ts +21 -0
  234. package/src/map-annotation/anchor.ts +92 -0
  235. package/src/map-annotation/index.ts +15 -0
  236. package/src/map-annotation/map-annotation.stories.tsx +113 -0
  237. package/src/map-annotation/map-annotation.test.tsx +106 -0
  238. package/src/map-annotation/map-annotation.tsx +356 -0
  239. package/src/map-arc/map-arc.tsx +26 -5
  240. package/src/map-canvas/map-canvas.stories.tsx +211 -0
  241. package/src/map-canvas/map-canvas.test.tsx +389 -0
  242. package/src/map-canvas/map-canvas.tsx +457 -17
  243. package/src/map-canvas/map-context.ts +11 -0
  244. package/src/map-cluster-layer/map-cluster-layer.tsx +14 -1
  245. package/src/map-controls/map-controls.stories.tsx +16 -0
  246. package/src/map-controls/map-controls.test.tsx +145 -1
  247. package/src/map-controls/map-controls.tsx +57 -12
  248. package/src/map-geojson/map-geojson.stories.tsx +153 -3
  249. package/src/map-geojson/map-geojson.test.tsx +453 -0
  250. package/src/map-geojson/map-geojson.tsx +591 -51
  251. package/src/map-inset/index.ts +1 -0
  252. package/src/map-inset/map-inset.stories.tsx +61 -0
  253. package/src/map-inset/map-inset.test.tsx +117 -0
  254. package/src/map-inset/map-inset.tsx +264 -0
  255. package/src/map-legend/index.ts +10 -0
  256. package/src/map-legend/map-corner.ts +23 -0
  257. package/src/map-legend/map-legend.stories.tsx +171 -0
  258. package/src/map-legend/map-legend.test.tsx +136 -0
  259. package/src/map-legend/map-legend.tsx +264 -0
  260. package/src/map-marker/map-marker.stories.tsx +136 -4
  261. package/src/map-marker/map-marker.test.tsx +328 -3
  262. package/src/map-marker/map-marker.tsx +370 -33
  263. package/src/map-north-arrow/index.ts +1 -0
  264. package/src/map-north-arrow/map-north-arrow.stories.tsx +65 -0
  265. package/src/map-north-arrow/map-north-arrow.test.tsx +39 -0
  266. package/src/map-north-arrow/map-north-arrow.tsx +82 -0
  267. package/src/map-plan/index.ts +13 -0
  268. package/src/map-plan/map-plan-legend.test.tsx +61 -0
  269. package/src/map-plan/map-plan-legend.tsx +83 -0
  270. package/src/map-plan/map-plan-overlay.stories.tsx +260 -0
  271. package/src/map-plan/map-plan-overlay.test.tsx +302 -0
  272. package/src/map-plan/map-plan-overlay.tsx +531 -0
  273. package/src/map-plan/map-plan-status.test.tsx +71 -0
  274. package/src/map-plan/map-plan-status.tsx +77 -0
  275. package/src/map-plan/map-plan-table.test.tsx +86 -0
  276. package/src/map-plan/map-plan-table.tsx +153 -0
  277. package/src/map-plan/use-plan-selection.ts +78 -0
  278. package/src/map-plan-image/index.ts +1 -0
  279. package/src/map-plan-image/map-plan-image.stories.tsx +301 -0
  280. package/src/map-plan-image/map-plan-image.test.tsx +176 -0
  281. package/src/map-plan-image/map-plan-image.tsx +279 -0
  282. package/src/map-popup/map-popup.tsx +15 -10
  283. package/src/map-route/index.ts +1 -1
  284. package/src/map-route/map-route.test.tsx +216 -0
  285. package/src/map-route/map-route.tsx +105 -6
  286. package/src/map-scale-bar/index.ts +9 -0
  287. package/src/map-scale-bar/map-scale-bar.stories.tsx +63 -0
  288. package/src/map-scale-bar/map-scale-bar.test.tsx +65 -0
  289. package/src/map-scale-bar/map-scale-bar.tsx +145 -0
  290. package/src/test-utils/locator-fixture.ts +75 -0
  291. package/src/test-utils/maplibre-mock.ts +256 -19
@@ -0,0 +1,201 @@
1
+ "use client";
2
+ import {
3
+ useTokenColor
4
+ } from "./chunk-Y44MEKJV.js";
5
+ import {
6
+ useMap
7
+ } from "./chunk-JYFERXZT.js";
8
+ import {
9
+ buildArcCoordinates
10
+ } from "./chunk-BGCE3RR5.js";
11
+ import {
12
+ mergeHoverPaint
13
+ } from "./chunk-RNSLG64F.js";
14
+
15
+ // src/map-arc/map-arc.tsx
16
+ import { useEffect, useId, useMemo, useRef } from "react";
17
+ var DEFAULT_ARC_CURVATURE = 0.2;
18
+ var DEFAULT_ARC_SAMPLES = 64;
19
+ var ARC_HIT_MIN_WIDTH = 12;
20
+ var ARC_HIT_PADDING = 6;
21
+ var DEFAULT_ARC_LAYOUT = {
22
+ "line-join": "round",
23
+ "line-cap": "round"
24
+ };
25
+ function MapArc({
26
+ data,
27
+ id: propId,
28
+ curvature = DEFAULT_ARC_CURVATURE,
29
+ samples = DEFAULT_ARC_SAMPLES,
30
+ paint,
31
+ layout,
32
+ hoverPaint,
33
+ onClick,
34
+ onHover,
35
+ interactive = true,
36
+ beforeId
37
+ }) {
38
+ const { map, isLoaded, plan } = useMap();
39
+ const autoId = useId();
40
+ const id = propId ?? autoId;
41
+ const sourceId = `arc-source-${id}`;
42
+ const layerId = `arc-layer-${id}`;
43
+ const hitLayerId = `arc-hit-layer-${id}`;
44
+ const primary = useTokenColor("--primary");
45
+ const mergedPaint = useMemo(
46
+ () => mergeHoverPaint(
47
+ { "line-color": primary, "line-width": 2, "line-opacity": 0.85, ...paint },
48
+ hoverPaint
49
+ ),
50
+ [primary, paint, hoverPaint]
51
+ );
52
+ const mergedLayout = useMemo(() => ({ ...DEFAULT_ARC_LAYOUT, ...layout }), [layout]);
53
+ const hitWidth = useMemo(() => {
54
+ const w = paint?.["line-width"] ?? 2;
55
+ const base = typeof w === "number" ? w : ARC_HIT_MIN_WIDTH;
56
+ return Math.max(base + ARC_HIT_PADDING, ARC_HIT_MIN_WIDTH);
57
+ }, [paint]);
58
+ const geoJSON = useMemo(
59
+ () => ({
60
+ type: "FeatureCollection",
61
+ features: data.map((arc) => {
62
+ const { from, to, ...properties } = arc;
63
+ const sampled = buildArcCoordinates(from, to, curvature, samples, plan == null);
64
+ return {
65
+ type: "Feature",
66
+ properties,
67
+ geometry: {
68
+ type: "LineString",
69
+ coordinates: plan ? sampled.map((point) => plan.toLngLat(point)) : sampled
70
+ }
71
+ };
72
+ })
73
+ }),
74
+ [data, curvature, samples, plan]
75
+ );
76
+ const latestRef = useRef({ data, onClick, onHover });
77
+ latestRef.current = { data, onClick, onHover };
78
+ const planRef = useRef(plan);
79
+ planRef.current = plan;
80
+ useEffect(() => {
81
+ if (!isLoaded || !map) return;
82
+ map.addSource(sourceId, {
83
+ type: "geojson",
84
+ data: geoJSON,
85
+ promoteId: "id"
86
+ });
87
+ map.addLayer(
88
+ {
89
+ id: hitLayerId,
90
+ type: "line",
91
+ source: sourceId,
92
+ layout: DEFAULT_ARC_LAYOUT,
93
+ paint: {
94
+ "line-color": "transparent",
95
+ "line-width": hitWidth,
96
+ "line-opacity": 1
97
+ }
98
+ },
99
+ beforeId
100
+ );
101
+ map.addLayer(
102
+ {
103
+ id: layerId,
104
+ type: "line",
105
+ source: sourceId,
106
+ layout: mergedLayout,
107
+ paint: mergedPaint
108
+ },
109
+ beforeId
110
+ );
111
+ return () => {
112
+ try {
113
+ if (map.getLayer(layerId)) map.removeLayer(layerId);
114
+ if (map.getLayer(hitLayerId)) map.removeLayer(hitLayerId);
115
+ if (map.getSource(sourceId)) map.removeSource(sourceId);
116
+ } catch {
117
+ }
118
+ };
119
+ }, [isLoaded, map]);
120
+ useEffect(() => {
121
+ if (!isLoaded || !map) return;
122
+ const source = map.getSource(sourceId);
123
+ source?.setData(geoJSON);
124
+ }, [isLoaded, map, geoJSON, sourceId]);
125
+ useEffect(() => {
126
+ if (!isLoaded || !map || !map.getLayer(layerId)) return;
127
+ for (const [key, value] of Object.entries(mergedPaint)) {
128
+ map.setPaintProperty(layerId, key, value);
129
+ }
130
+ for (const [key, value] of Object.entries(mergedLayout)) {
131
+ map.setLayoutProperty(layerId, key, value);
132
+ }
133
+ if (map.getLayer(hitLayerId)) {
134
+ map.setPaintProperty(hitLayerId, "line-width", hitWidth);
135
+ }
136
+ }, [isLoaded, map, layerId, hitLayerId, mergedPaint, mergedLayout, hitWidth]);
137
+ useEffect(() => {
138
+ if (!isLoaded || !map || !interactive) return;
139
+ let hoveredId = null;
140
+ const setHover = (next) => {
141
+ if (next === hoveredId) return;
142
+ const sourceExists = !!map.getSource(sourceId);
143
+ if (hoveredId != null && sourceExists) {
144
+ map.setFeatureState({ source: sourceId, id: hoveredId }, { hover: false });
145
+ }
146
+ hoveredId = next;
147
+ if (next != null && sourceExists) {
148
+ map.setFeatureState({ source: sourceId, id: next }, { hover: true });
149
+ }
150
+ };
151
+ const findArc = (featureId) => featureId == null ? void 0 : latestRef.current.data.find((arc) => String(arc.id) === String(featureId));
152
+ const handleMouseMove = (e) => {
153
+ const featureId = e.features?.[0]?.id;
154
+ if (featureId == null || featureId === hoveredId) return;
155
+ setHover(featureId);
156
+ map.getCanvas().style.cursor = "pointer";
157
+ const arc = findArc(featureId);
158
+ if (arc) {
159
+ latestRef.current.onHover?.({
160
+ arc,
161
+ longitude: e.lngLat.lng,
162
+ latitude: e.lngLat.lat,
163
+ plan: planRef.current ? planRef.current.toPlan([e.lngLat.lng, e.lngLat.lat]) : null,
164
+ originalEvent: e
165
+ });
166
+ }
167
+ };
168
+ const handleMouseLeave = () => {
169
+ setHover(null);
170
+ map.getCanvas().style.cursor = "";
171
+ latestRef.current.onHover?.(null);
172
+ };
173
+ const handleClick = (e) => {
174
+ const arc = findArc(e.features?.[0]?.id);
175
+ if (!arc) return;
176
+ latestRef.current.onClick?.({
177
+ arc,
178
+ longitude: e.lngLat.lng,
179
+ latitude: e.lngLat.lat,
180
+ plan: planRef.current ? planRef.current.toPlan([e.lngLat.lng, e.lngLat.lat]) : null,
181
+ originalEvent: e
182
+ });
183
+ };
184
+ map.on("mousemove", hitLayerId, handleMouseMove);
185
+ map.on("mouseleave", hitLayerId, handleMouseLeave);
186
+ map.on("click", hitLayerId, handleClick);
187
+ return () => {
188
+ map.off("mousemove", hitLayerId, handleMouseMove);
189
+ map.off("mouseleave", hitLayerId, handleMouseLeave);
190
+ map.off("click", hitLayerId, handleClick);
191
+ setHover(null);
192
+ map.getCanvas().style.cursor = "";
193
+ };
194
+ }, [isLoaded, map, hitLayerId, sourceId, interactive]);
195
+ return null;
196
+ }
197
+
198
+ export {
199
+ MapArc
200
+ };
201
+ //# sourceMappingURL=chunk-OEVVNPN3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/map-arc/map-arc.tsx"],"sourcesContent":["\"use client\";\n\nimport type MapLibreGL from \"maplibre-gl\";\nimport { useEffect, useId, useMemo, useRef } from \"react\";\n\nimport { useMap } from \"../map-canvas/map-context\";\nimport { buildArcCoordinates } from \"../lib/arc-math\";\nimport type { PlanPoint } from \"../lib/plan-crs\";\nimport { mergeHoverPaint } from \"../lib/merge-hover-paint\";\nimport { useTokenColor } from \"../lib/use-token-color\";\n\n/** A single arc to render inside `<MapArc data={...}>`. */\nexport type MapArcDatum = {\n /** Unique identifier for this arc. Required for hover state tracking and event payloads. */\n id: string | number;\n /**\n * Start coordinate as [longitude, latitude] — or, inside a `<MapCanvas plan>`,\n * as [x, y] in plan units.\n */\n from: [number, number];\n /** End coordinate, in the same units as `from`. */\n to: [number, number];\n};\n\n/** Event payload passed to MapArc interaction callbacks. */\nexport type MapArcEvent<T extends MapArcDatum = MapArcDatum> = {\n /** The arc datum that was hovered or clicked. */\n arc: T;\n /** Longitude of the cursor at the time of the event. */\n longitude: number;\n /** Latitude of the cursor at the time of the event. */\n latitude: number;\n /** The cursor in plan units, on a plan map; `null` on a geographic one. */\n plan: PlanPoint | null;\n /** The underlying MapLibre mouse event for advanced use cases. */\n originalEvent: MapLibreGL.MapMouseEvent;\n};\n\nexport type MapArcLinePaint = NonNullable<MapLibreGL.LineLayerSpecification[\"paint\"]>;\nexport type MapArcLineLayout = NonNullable<MapLibreGL.LineLayerSpecification[\"layout\"]>;\n\nexport type MapArcProps<T extends MapArcDatum = MapArcDatum> = {\n /** Array of arcs to render. Each arc must have a unique `id`. */\n data: T[];\n /** Optional unique identifier prefix for the arc source/layers. Auto-generated if not provided. */\n id?: string;\n /**\n * How far each arc bows away from a straight line. `0` renders straight\n * lines; higher values bend further; negative values bend to the opposite\n * side. Arcs cross the antimeridian via the shorter direction. (default: 0.2)\n */\n curvature?: number;\n /** Number of samples used to render each curve. Higher = smoother. (default: 64) */\n samples?: number;\n /**\n * MapLibre paint properties for the arc layer. Merged on top of theme-aware\n * defaults (`line-color` = the `--primary` token, `line-width: 2`,\n * `line-opacity: 0.85`). Any value can be a MapLibre expression for\n * per-feature styling; every field on each arc datum (besides `from`/`to`)\n * is exposed via `[\"get\", ...]`.\n */\n paint?: MapArcLinePaint;\n /** MapLibre layout properties for the arc layer. Defaults to rounded joins/caps. */\n layout?: MapArcLineLayout;\n /**\n * Paint properties applied to the arc currently under the cursor. Each key\n * is merged into `paint` as a `case` expression keyed on per-feature hover\n * state, so only the hovered arc changes appearance.\n */\n hoverPaint?: MapArcLinePaint;\n /** Callback when an arc is clicked. */\n onClick?: (e: MapArcEvent<T>) => void;\n /**\n * Callback fired when the hovered arc changes. Receives the cursor's\n * lng/lat at the moment of entry, and `null` when the cursor leaves the\n * last hovered arc.\n */\n onHover?: (e: MapArcEvent<T> | null) => void;\n /** Whether arcs respond to mouse events (default: true). */\n interactive?: boolean;\n /** Optional MapLibre layer id to insert the arc layers before (z-order control). */\n beforeId?: string;\n};\n\nconst DEFAULT_ARC_CURVATURE = 0.2;\nconst DEFAULT_ARC_SAMPLES = 64;\nconst ARC_HIT_MIN_WIDTH = 12;\nconst ARC_HIT_PADDING = 6;\n\nconst DEFAULT_ARC_LAYOUT: MapArcLineLayout = {\n \"line-join\": \"round\",\n \"line-cap\": \"round\",\n};\n\n/**\n * Curved great-circle-style arcs between coordinate pairs (flight paths,\n * network links). Pairs well with `<MapCanvas blank projection={{ type: \"globe\" }}>`.\n *\n * Inside a `<MapCanvas plan>` the same component draws plan-space curves — a\n * material flow between two machine cells, a walking route across a floor. The\n * curve is built in PLAN units and each sample is then converted, because a\n * straight lng/lat line bows once Mercator has had its say.\n */\nexport function MapArc<T extends MapArcDatum = MapArcDatum>({\n data,\n id: propId,\n curvature = DEFAULT_ARC_CURVATURE,\n samples = DEFAULT_ARC_SAMPLES,\n paint,\n layout,\n hoverPaint,\n onClick,\n onHover,\n interactive = true,\n beforeId,\n}: MapArcProps<T>) {\n const { map, isLoaded, plan } = useMap();\n const autoId = useId();\n const id = propId ?? autoId;\n const sourceId = `arc-source-${id}`;\n const layerId = `arc-layer-${id}`;\n const hitLayerId = `arc-hit-layer-${id}`;\n\n const primary = useTokenColor(\"--primary\");\n\n const mergedPaint = useMemo(\n () =>\n mergeHoverPaint(\n { \"line-color\": primary, \"line-width\": 2, \"line-opacity\": 0.85, ...paint },\n hoverPaint,\n ),\n [primary, paint, hoverPaint],\n );\n const mergedLayout = useMemo(() => ({ ...DEFAULT_ARC_LAYOUT, ...layout }), [layout]);\n\n const hitWidth = useMemo(() => {\n const w = paint?.[\"line-width\"] ?? 2;\n const base = typeof w === \"number\" ? w : ARC_HIT_MIN_WIDTH;\n return Math.max(base + ARC_HIT_PADDING, ARC_HIT_MIN_WIDTH);\n }, [paint]);\n\n const geoJSON = useMemo<GeoJSON.FeatureCollection<GeoJSON.LineString>>(\n () => ({\n type: \"FeatureCollection\",\n features: data.map((arc) => {\n const { from, to, ...properties } = arc;\n // In plan mode the curve is sampled in plan units with the antimeridian\n // unwrap OFF — x is a position on a floor, not a longitude — and each\n // sample is converted afterwards.\n const sampled = buildArcCoordinates(from, to, curvature, samples, plan == null);\n return {\n type: \"Feature\",\n properties,\n geometry: {\n type: \"LineString\",\n coordinates: plan ? sampled.map((point) => plan.toLngLat(point)) : sampled,\n },\n };\n }),\n }),\n [data, curvature, samples, plan],\n );\n\n const latestRef = useRef({ data, onClick, onHover });\n latestRef.current = { data, onClick, onHover };\n // The interaction effect is bound once per map; the plan is read through a ref\n // so a plan arriving later does not rebind every listener.\n const planRef = useRef(plan);\n planRef.current = plan;\n\n // Add source and layers on mount. The invisible hit layer widens the\n // pointer target so thin arcs stay hoverable/clickable.\n useEffect(() => {\n if (!isLoaded || !map) return;\n\n map.addSource(sourceId, {\n type: \"geojson\",\n data: geoJSON,\n promoteId: \"id\",\n });\n\n map.addLayer(\n {\n id: hitLayerId,\n type: \"line\",\n source: sourceId,\n layout: DEFAULT_ARC_LAYOUT,\n paint: {\n \"line-color\": \"transparent\",\n \"line-width\": hitWidth,\n \"line-opacity\": 1,\n },\n },\n beforeId,\n );\n\n map.addLayer(\n {\n id: layerId,\n type: \"line\",\n source: sourceId,\n layout: mergedLayout,\n paint: mergedPaint,\n },\n beforeId,\n );\n\n return () => {\n try {\n if (map.getLayer(layerId)) map.removeLayer(layerId);\n if (map.getLayer(hitLayerId)) map.removeLayer(hitLayerId);\n if (map.getSource(sourceId)) map.removeSource(sourceId);\n } catch {\n // style may be mid-reload\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- source/layers created once per map; data + paint are synced by the effects below\n }, [isLoaded, map]);\n\n // Sync features when data / curvature / samples change.\n useEffect(() => {\n if (!isLoaded || !map) return;\n const source = map.getSource(sourceId) as MapLibreGL.GeoJSONSource | undefined;\n source?.setData(geoJSON);\n }, [isLoaded, map, geoJSON, sourceId]);\n\n // Sync paint/layout when they change.\n useEffect(() => {\n if (!isLoaded || !map || !map.getLayer(layerId)) return;\n for (const [key, value] of Object.entries(mergedPaint)) {\n map.setPaintProperty(layerId, key as keyof MapArcLinePaint, value as never);\n }\n for (const [key, value] of Object.entries(mergedLayout)) {\n map.setLayoutProperty(layerId, key as keyof MapArcLineLayout, value as never);\n }\n if (map.getLayer(hitLayerId)) {\n map.setPaintProperty(hitLayerId, \"line-width\", hitWidth);\n }\n }, [isLoaded, map, layerId, hitLayerId, mergedPaint, mergedLayout, hitWidth]);\n\n // Interaction handlers (bound to the hit layer).\n useEffect(() => {\n if (!isLoaded || !map || !interactive) return;\n\n let hoveredId: string | number | null = null;\n\n const setHover = (next: string | number | null) => {\n if (next === hoveredId) return;\n const sourceExists = !!map.getSource(sourceId);\n if (hoveredId != null && sourceExists) {\n map.setFeatureState({ source: sourceId, id: hoveredId }, { hover: false });\n }\n hoveredId = next;\n if (next != null && sourceExists) {\n map.setFeatureState({ source: sourceId, id: next }, { hover: true });\n }\n };\n\n const findArc = (featureId: string | number | undefined) =>\n featureId == null\n ? undefined\n : latestRef.current.data.find((arc) => String(arc.id) === String(featureId));\n\n const handleMouseMove = (e: MapLibreGL.MapLayerMouseEvent) => {\n const featureId = e.features?.[0]?.id as string | number | undefined;\n if (featureId == null || featureId === hoveredId) return;\n\n setHover(featureId);\n map.getCanvas().style.cursor = \"pointer\";\n\n const arc = findArc(featureId);\n if (arc) {\n latestRef.current.onHover?.({\n arc: arc as T,\n longitude: e.lngLat.lng,\n latitude: e.lngLat.lat,\n plan: planRef.current ? planRef.current.toPlan([e.lngLat.lng, e.lngLat.lat]) : null,\n originalEvent: e,\n });\n }\n };\n\n const handleMouseLeave = () => {\n setHover(null);\n map.getCanvas().style.cursor = \"\";\n latestRef.current.onHover?.(null);\n };\n\n const handleClick = (e: MapLibreGL.MapLayerMouseEvent) => {\n const arc = findArc(e.features?.[0]?.id as string | number | undefined);\n if (!arc) return;\n latestRef.current.onClick?.({\n arc: arc as T,\n longitude: e.lngLat.lng,\n latitude: e.lngLat.lat,\n plan: planRef.current ? planRef.current.toPlan([e.lngLat.lng, e.lngLat.lat]) : null,\n originalEvent: e,\n });\n };\n\n map.on(\"mousemove\", hitLayerId, handleMouseMove);\n map.on(\"mouseleave\", hitLayerId, handleMouseLeave);\n map.on(\"click\", hitLayerId, handleClick);\n\n return () => {\n map.off(\"mousemove\", hitLayerId, handleMouseMove);\n map.off(\"mouseleave\", hitLayerId, handleMouseLeave);\n map.off(\"click\", hitLayerId, handleClick);\n setHover(null);\n map.getCanvas().style.cursor = \"\";\n };\n }, [isLoaded, map, hitLayerId, sourceId, interactive]);\n\n return null;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,200 @@
1
+ "use client";
2
+ import {
3
+ MAP_CORNER_CLASSES
4
+ } from "./chunk-GWULZOMW.js";
5
+ import {
6
+ MapCanvas
7
+ } from "./chunk-XQT7YLJY.js";
8
+ import {
9
+ useTokenColor
10
+ } from "./chunk-Y44MEKJV.js";
11
+ import {
12
+ useMapResponsive
13
+ } from "./chunk-W76NLFER.js";
14
+ import {
15
+ useMap
16
+ } from "./chunk-JYFERXZT.js";
17
+
18
+ // src/map-inset/map-inset.tsx
19
+ import { forwardRef, useEffect, useId, useState } from "react";
20
+ import { cn } from "@elabs-ai/components-ui/lib/cn";
21
+ import { jsx } from "react/jsx-runtime";
22
+ var REGION_ZOOM_OUT = 4;
23
+ var MIN_BOX_PX = 6;
24
+ function readView(map) {
25
+ const center = map.getCenter();
26
+ const bounds = map.getBounds();
27
+ return {
28
+ center: [center.lng, center.lat],
29
+ zoom: map.getZoom(),
30
+ bounds: [bounds.getWest(), bounds.getSouth(), bounds.getEast(), bounds.getNorth()]
31
+ };
32
+ }
33
+ function globeZoom(width) {
34
+ const scale = 0.9 * width * Math.PI / 512;
35
+ return Math.log2(Math.max(scale, 1e-3));
36
+ }
37
+ function InsetFollower({ view, kind }) {
38
+ const { map, isLoaded } = useMap();
39
+ const id = useId();
40
+ const sourceId = `map-inset-view-${id}`;
41
+ const lineId = `map-inset-box-${id}`;
42
+ const fillId = `map-inset-fill-${id}`;
43
+ const dotId = `map-inset-dot-${id}`;
44
+ const accent = useTokenColor("--primary");
45
+ const surface = useTokenColor("--background");
46
+ const [boxWidth, setBoxWidth] = useState(0);
47
+ useEffect(() => {
48
+ if (!map) return void 0;
49
+ const update = () => setBoxWidth(map.getContainer().clientWidth);
50
+ update();
51
+ map.on("resize", update);
52
+ return () => {
53
+ map.off("resize", update);
54
+ };
55
+ }, [map]);
56
+ useEffect(() => {
57
+ if (!map || !isLoaded) return void 0;
58
+ map.addSource(sourceId, { type: "geojson", data: { type: "FeatureCollection", features: [] } });
59
+ map.addLayer({
60
+ id: fillId,
61
+ type: "fill",
62
+ source: sourceId,
63
+ filter: ["==", ["geometry-type"], "Polygon"],
64
+ paint: { "fill-color": accent, "fill-opacity": 0.2 }
65
+ });
66
+ map.addLayer({
67
+ id: lineId,
68
+ type: "line",
69
+ source: sourceId,
70
+ filter: ["==", ["geometry-type"], "Polygon"],
71
+ paint: { "line-color": accent, "line-width": 1.5 }
72
+ });
73
+ map.addLayer({
74
+ id: dotId,
75
+ type: "circle",
76
+ source: sourceId,
77
+ filter: ["==", ["geometry-type"], "Point"],
78
+ paint: {
79
+ "circle-color": accent,
80
+ "circle-radius": 3.5,
81
+ "circle-stroke-color": surface,
82
+ "circle-stroke-width": 1
83
+ }
84
+ });
85
+ return () => {
86
+ try {
87
+ for (const layer of [dotId, lineId, fillId])
88
+ if (map.getLayer(layer)) map.removeLayer(layer);
89
+ if (map.getSource(sourceId)) map.removeSource(sourceId);
90
+ } catch {
91
+ }
92
+ };
93
+ }, [map, isLoaded]);
94
+ useEffect(() => {
95
+ if (!map || !isLoaded) return;
96
+ if (map.getLayer(fillId)) map.setPaintProperty(fillId, "fill-color", accent);
97
+ if (map.getLayer(lineId)) map.setPaintProperty(lineId, "line-color", accent);
98
+ if (map.getLayer(dotId)) {
99
+ map.setPaintProperty(dotId, "circle-color", accent);
100
+ map.setPaintProperty(dotId, "circle-stroke-color", surface);
101
+ }
102
+ }, [map, isLoaded, accent, surface, fillId, lineId, dotId]);
103
+ useEffect(() => {
104
+ if (!map || !isLoaded) return;
105
+ const width = boxWidth || map.getContainer().clientWidth;
106
+ const zoom = kind === "globe" ? globeZoom(width) : Math.max(0, view.zoom - REGION_ZOOM_OUT);
107
+ map.jumpTo({ center: view.center, zoom });
108
+ const [west, south, east, north] = view.bounds;
109
+ const a = map.project([west, north]);
110
+ const b = map.project([east, south]);
111
+ const small = Math.abs(b.x - a.x) < MIN_BOX_PX && Math.abs(b.y - a.y) < MIN_BOX_PX;
112
+ const feature = small ? { type: "Feature", properties: {}, geometry: { type: "Point", coordinates: view.center } } : {
113
+ type: "Feature",
114
+ properties: {},
115
+ geometry: {
116
+ type: "Polygon",
117
+ coordinates: [
118
+ [
119
+ [west, south],
120
+ [east, south],
121
+ [east, north],
122
+ [west, north],
123
+ [west, south]
124
+ ]
125
+ ]
126
+ }
127
+ };
128
+ const source = map.getSource(sourceId);
129
+ source?.setData?.({ type: "FeatureCollection", features: [feature] });
130
+ }, [map, isLoaded, kind, view, sourceId, boxWidth]);
131
+ return null;
132
+ }
133
+ var MapInset = forwardRef(function MapInset2({
134
+ kind = "globe",
135
+ position = "top-right",
136
+ size: sizeProp = { base: 128, narrow: 88 },
137
+ styles,
138
+ blank,
139
+ basemapLabels = false,
140
+ className,
141
+ style,
142
+ ...props
143
+ }, ref) {
144
+ const { map } = useMap();
145
+ const size = Math.max(0, useMapResponsive(sizeProp));
146
+ const [view, setView] = useState(() => map ? readView(map) : null);
147
+ useEffect(() => {
148
+ if (!map) return void 0;
149
+ const update = () => setView(readView(map));
150
+ update();
151
+ map.on("moveend", update);
152
+ map.on("resize", update);
153
+ return () => {
154
+ map.off("moveend", update);
155
+ map.off("resize", update);
156
+ };
157
+ }, [map]);
158
+ return /* @__PURE__ */ jsx(
159
+ "div",
160
+ {
161
+ ref,
162
+ "aria-hidden": "true",
163
+ "data-slot": "map-inset",
164
+ "data-kind": kind,
165
+ className: cn(
166
+ "pointer-events-none absolute z-10 overflow-hidden bg-background shadow-ring-sm",
167
+ kind === "globe" ? "rounded-full" : "rounded-md",
168
+ MAP_CORNER_CLASSES[position],
169
+ className
170
+ ),
171
+ style: {
172
+ width: size,
173
+ maxWidth: "40%",
174
+ aspectRatio: "1 / 1",
175
+ transitionProperty: "none",
176
+ ...style
177
+ },
178
+ ...props,
179
+ children: view && /* @__PURE__ */ jsx(
180
+ MapCanvas,
181
+ {
182
+ interactive: false,
183
+ center: view.center,
184
+ zoom: kind === "globe" ? 0 : Math.max(0, view.zoom - REGION_ZOOM_OUT),
185
+ minZoom: -2,
186
+ projection: kind === "globe" ? "globe" : void 0,
187
+ styles,
188
+ blank,
189
+ basemapLabels,
190
+ children: /* @__PURE__ */ jsx(InsetFollower, { view, kind })
191
+ }
192
+ )
193
+ }
194
+ );
195
+ });
196
+
197
+ export {
198
+ MapInset
199
+ };
200
+ //# sourceMappingURL=chunk-PF3R2BXM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/map-inset/map-inset.tsx"],"sourcesContent":["\"use client\";\n\nimport { forwardRef, useEffect, useId, useState, type HTMLAttributes } from \"react\";\nimport { cn } from \"@elabs-ai/components-ui/lib/cn\";\n\nimport { MapCanvas, type MapCanvasProps } from \"../map-canvas/map-canvas\";\nimport { useMap } from \"../map-canvas/map-context\";\nimport { type MapResponsive, useMapResponsive } from \"../lib/use-map-breakpoint\";\nimport { useTokenColor } from \"../lib/use-token-color\";\nimport { MAP_CORNER_CLASSES, type MapCorner } from \"../map-legend/map-corner\";\n\n/** A globe with the main view marked, or a zoomed-out regional map around it. */\nexport type MapInsetKind = \"globe\" | \"region\";\n\nexport interface MapInsetProps extends HTMLAttributes<HTMLDivElement> {\n /** Default `\"globe\"`. */\n kind?: MapInsetKind;\n /** Corner of the main map (default `\"top-right\"`). */\n position?: MapCorner;\n /**\n * Side length in CSS px, optionally per tier (default\n * `{ base: 128, narrow: 88 }`). Never more than 40 % of the main map's width.\n */\n size?: MapResponsive<number>;\n /** Basemap styles for the inset (default: the main map's defaults). */\n styles?: MapCanvasProps[\"styles\"];\n /** A tile-less inset — pair it with your own layers via `styles`. */\n blank?: boolean;\n /**\n * Draw the basemap's own place labels inside the inset. Default `false`\n * (c-6): a basemap's labels are sized for a full map, so in an 88–128 px\n * frame they are sliced mid-word (\"EUROP\", \"AMERIC\") and read louder than\n * the globe they caption. An inset is a locator SHAPE, not a second map.\n */\n basemapLabels?: boolean;\n}\n\n/** How many zoom levels a `region` inset sits below the main map. */\nconst REGION_ZOOM_OUT = 4;\n/** Below this many px across, the main view is marked as a dot, not a box. */\nconst MIN_BOX_PX = 6;\n\ninterface MainView {\n center: [number, number];\n zoom: number;\n bounds: [west: number, south: number, east: number, north: number];\n}\n\nfunction readView(map: NonNullable<ReturnType<typeof useMap>[\"map\"]>): MainView {\n const center = map.getCenter();\n const bounds = map.getBounds();\n return {\n center: [center.lng, center.lat],\n zoom: map.getZoom(),\n bounds: [bounds.getWest(), bounds.getSouth(), bounds.getEast(), bounds.getNorth()],\n };\n}\n\n/**\n * The zoom at which a globe fills ~90 % of a `width`-px box.\n *\n * Latitude-independent on purpose (c-6): the old `cos(latitude)` factor is\n * Mercator's scale correction, and a globe projection does not stretch with\n * latitude — it only made the sphere shrink the further the main map sat from\n * the equator (a Toronto locator's globe came out ~28 % narrower than the same\n * globe over the Gulf of Guinea).\n */\nfunction globeZoom(width: number): number {\n const scale = (0.9 * width * Math.PI) / 512;\n return Math.log2(Math.max(scale, 1e-3));\n}\n\n/** Inside the inset canvas: follows the main view and marks its extent. */\nfunction InsetFollower({ view, kind }: { view: MainView; kind: MapInsetKind }) {\n const { map, isLoaded } = useMap();\n const id = useId();\n const sourceId = `map-inset-view-${id}`;\n const lineId = `map-inset-box-${id}`;\n const fillId = `map-inset-fill-${id}`;\n const dotId = `map-inset-dot-${id}`;\n const accent = useTokenColor(\"--primary\");\n const surface = useTokenColor(\"--background\");\n\n // The inset's own box is responsive: `size` resolves at the MAIN map's tier,\n // which is measured one render after the inset canvas is built, so a narrow\n // inset is created 128 px wide and settles at 88. A globe is zoomed to fill\n // its box, so that zoom has to be recomputed when the box changes.\n const [boxWidth, setBoxWidth] = useState(0);\n useEffect(() => {\n if (!map) return undefined;\n const update = () => setBoxWidth(map.getContainer().clientWidth);\n update();\n map.on(\"resize\", update);\n return () => {\n map.off(\"resize\", update);\n };\n }, [map]);\n\n useEffect(() => {\n if (!map || !isLoaded) return undefined;\n map.addSource(sourceId, { type: \"geojson\", data: { type: \"FeatureCollection\", features: [] } });\n map.addLayer({\n id: fillId,\n type: \"fill\",\n source: sourceId,\n filter: [\"==\", [\"geometry-type\"], \"Polygon\"],\n paint: { \"fill-color\": accent, \"fill-opacity\": 0.2 },\n });\n map.addLayer({\n id: lineId,\n type: \"line\",\n source: sourceId,\n filter: [\"==\", [\"geometry-type\"], \"Polygon\"],\n paint: { \"line-color\": accent, \"line-width\": 1.5 },\n });\n map.addLayer({\n id: dotId,\n type: \"circle\",\n source: sourceId,\n filter: [\"==\", [\"geometry-type\"], \"Point\"],\n paint: {\n \"circle-color\": accent,\n \"circle-radius\": 3.5,\n \"circle-stroke-color\": surface,\n \"circle-stroke-width\": 1,\n },\n });\n return () => {\n try {\n for (const layer of [dotId, lineId, fillId])\n if (map.getLayer(layer)) map.removeLayer(layer);\n if (map.getSource(sourceId)) map.removeSource(sourceId);\n } catch {\n // style may be mid-reload\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- layers created once per load; colours synced below\n }, [map, isLoaded]);\n\n useEffect(() => {\n if (!map || !isLoaded) return;\n if (map.getLayer(fillId)) map.setPaintProperty(fillId, \"fill-color\", accent);\n if (map.getLayer(lineId)) map.setPaintProperty(lineId, \"line-color\", accent);\n if (map.getLayer(dotId)) {\n map.setPaintProperty(dotId, \"circle-color\", accent);\n map.setPaintProperty(dotId, \"circle-stroke-color\", surface);\n }\n }, [map, isLoaded, accent, surface, fillId, lineId, dotId]);\n\n useEffect(() => {\n if (!map || !isLoaded) return;\n const width = boxWidth || map.getContainer().clientWidth;\n const zoom = kind === \"globe\" ? globeZoom(width) : Math.max(0, view.zoom - REGION_ZOOM_OUT);\n map.jumpTo({ center: view.center, zoom });\n\n const [west, south, east, north] = view.bounds;\n const a = map.project([west, north]);\n const b = map.project([east, south]);\n const small = Math.abs(b.x - a.x) < MIN_BOX_PX && Math.abs(b.y - a.y) < MIN_BOX_PX;\n const feature: GeoJSON.Feature = small\n ? { type: \"Feature\", properties: {}, geometry: { type: \"Point\", coordinates: view.center } }\n : {\n type: \"Feature\",\n properties: {},\n geometry: {\n type: \"Polygon\",\n coordinates: [\n [\n [west, south],\n [east, south],\n [east, north],\n [west, north],\n [west, south],\n ],\n ],\n },\n };\n const source = map.getSource(sourceId) as { setData?: (data: unknown) => void } | undefined;\n source?.setData?.({ type: \"FeatureCollection\", features: [feature] });\n }, [map, isLoaded, kind, view, sourceId, boxWidth]);\n\n return null;\n}\n\n/**\n * MapInset — a small locator map in a corner of the main map: a globe\n * (`kind=\"globe\"`) or a zoomed-out regional map (`kind=\"region\"`), with the\n * main map's current view marked (a box, or a dot when the box would be too\n * small to see). It is a second, static `<MapCanvas>` that follows the main\n * view; decorative, so hidden from assistive tech and never a tab stop.\n * Render inside `<MapCanvas>`.\n */\nexport const MapInset = forwardRef<HTMLDivElement, MapInsetProps>(function MapInset(\n {\n kind = \"globe\",\n position = \"top-right\",\n size: sizeProp = { base: 128, narrow: 88 },\n styles,\n blank,\n basemapLabels = false,\n className,\n style,\n ...props\n },\n ref,\n) {\n const { map } = useMap();\n const size = Math.max(0, useMapResponsive(sizeProp));\n const [view, setView] = useState<MainView | null>(() => (map ? readView(map) : null));\n\n useEffect(() => {\n if (!map) return undefined;\n const update = () => setView(readView(map));\n update();\n map.on(\"moveend\", update);\n map.on(\"resize\", update);\n return () => {\n map.off(\"moveend\", update);\n map.off(\"resize\", update);\n };\n }, [map]);\n\n return (\n <div\n ref={ref}\n aria-hidden=\"true\"\n data-slot=\"map-inset\"\n data-kind={kind}\n className={cn(\n \"pointer-events-none absolute z-10 overflow-hidden bg-background shadow-ring-sm\",\n kind === \"globe\" ? \"rounded-full\" : \"rounded-md\",\n MAP_CORNER_CLASSES[position],\n className,\n )}\n // `transitionProperty: none` for the same reason `<MapCanvas>` pins it: a\n // transitioned width (the reduced-motion clamp gives EVERY element a\n // 0.01 ms duration) only lands on the next animation frame, and the\n // engine inside measures this box.\n style={{\n width: size,\n maxWidth: \"40%\",\n aspectRatio: \"1 / 1\",\n transitionProperty: \"none\",\n ...style,\n }}\n {...props}\n >\n {view && (\n <MapCanvas\n interactive={false}\n center={view.center}\n zoom={kind === \"globe\" ? 0 : Math.max(0, view.zoom - REGION_ZOOM_OUT)}\n minZoom={-2}\n projection={kind === \"globe\" ? \"globe\" : undefined}\n styles={styles}\n blank={blank}\n basemapLabels={basemapLabels}\n >\n <InsetFollower view={view} kind={kind} />\n </MapCanvas>\n )}\n </div>\n );\n});\n"],"mappings":"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","names":["MapInset"]}
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ //# sourceMappingURL=chunk-Q2I5YODW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}