isard 1.0.0 → 1.2.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 (268) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/dist/{basemaps.d.ts → basemap/basemaps.d.ts} +3 -3
  3. package/dist/{basemaps.js → basemap/basemaps.js} +3 -3
  4. package/dist/basemap/basemaps.js.map +1 -0
  5. package/dist/{grid.d.ts → basemap/grid.d.ts} +6 -6
  6. package/dist/{grid.js → basemap/grid.js} +61 -67
  7. package/dist/basemap/grid.js.map +1 -0
  8. package/dist/{mvt.d.ts → basemap/mvt.d.ts} +1 -1
  9. package/dist/{mvt.js → basemap/mvt.js} +6 -6
  10. package/dist/basemap/mvt.js.map +1 -0
  11. package/dist/{pmtiles.d.ts → basemap/pmtiles.d.ts} +16 -10
  12. package/dist/{pmtiles.js → basemap/pmtiles.js} +41 -33
  13. package/dist/basemap/pmtiles.js.map +1 -0
  14. package/dist/{resample.d.ts → basemap/resample.d.ts} +11 -2
  15. package/dist/{resample.js → basemap/resample.js} +18 -16
  16. package/dist/basemap/resample.js.map +1 -0
  17. package/dist/{terrain.d.ts → basemap/terrain.d.ts} +3 -3
  18. package/dist/{terrain.js → basemap/terrain.js} +7 -7
  19. package/dist/basemap/terrain.js.map +1 -0
  20. package/dist/{vectorstyle.d.ts → basemap/vectorstyle.d.ts} +12 -10
  21. package/dist/{vectorstyle.js → basemap/vectorstyle.js} +129 -111
  22. package/dist/basemap/vectorstyle.js.map +1 -0
  23. package/dist/{vectortiles.d.ts → basemap/vectortiles.d.ts} +18 -18
  24. package/dist/{vectortiles.js → basemap/vectortiles.js} +157 -109
  25. package/dist/basemap/vectortiles.js.map +1 -0
  26. package/dist/{wmts.d.ts → basemap/wmts.d.ts} +3 -3
  27. package/dist/{wmts.js → basemap/wmts.js} +19 -14
  28. package/dist/basemap/wmts.js.map +1 -0
  29. package/dist/basemap.worker.js +2 -2
  30. package/dist/basemap.worker.js.map +14 -13
  31. package/dist/bind/layers.d.ts +46 -0
  32. package/dist/bind/layers.js +154 -0
  33. package/dist/bind/layers.js.map +1 -0
  34. package/dist/{crs.d.ts → data/crs.d.ts} +11 -11
  35. package/dist/{crs.js → data/crs.js} +38 -34
  36. package/dist/data/crs.js.map +1 -0
  37. package/dist/{gpx.d.ts → data/gpx.d.ts} +2 -2
  38. package/dist/{gpx.js → data/gpx.js} +20 -20
  39. package/dist/data/gpx.js.map +1 -0
  40. package/dist/{kml.d.ts → data/kml.d.ts} +2 -2
  41. package/dist/{kml.js → data/kml.js} +42 -39
  42. package/dist/data/kml.js.map +1 -0
  43. package/dist/{topojson.d.ts → data/topojson.d.ts} +2 -2
  44. package/dist/{topojson.js → data/topojson.js} +15 -10
  45. package/dist/data/topojson.js.map +1 -0
  46. package/dist/{xml.d.ts → data/xml.d.ts} +5 -5
  47. package/dist/{xml.js → data/xml.js} +19 -18
  48. package/dist/data/xml.js.map +1 -0
  49. package/dist/decoder.worker.js +4 -4
  50. package/dist/decoder.worker.js.map +7 -7
  51. package/dist/{decoders.d.ts → engine/decoders.d.ts} +3 -3
  52. package/dist/{decoders.js → engine/decoders.js} +28 -25
  53. package/dist/engine/decoders.js.map +1 -0
  54. package/dist/{loader.d.ts → engine/loader.d.ts} +1 -1
  55. package/dist/{loader.js → engine/loader.js} +17 -14
  56. package/dist/engine/loader.js.map +1 -0
  57. package/dist/{protocol.d.ts → engine/protocol.d.ts} +1 -1
  58. package/dist/engine/protocol.js +3 -0
  59. package/dist/engine/protocol.js.map +1 -0
  60. package/dist/{requests.d.ts → engine/requests.d.ts} +1 -1
  61. package/dist/{requests.js → engine/requests.js} +19 -16
  62. package/dist/engine/requests.js.map +1 -0
  63. package/dist/engine-loader.d.ts +13 -9
  64. package/dist/engine-loader.js +30 -30
  65. package/dist/engine-loader.js.map +1 -1
  66. package/dist/formats.d.ts +3 -3
  67. package/dist/formats.js +3 -3
  68. package/dist/formats.js.map +1 -1
  69. package/dist/geoplateforme.d.ts +13 -13
  70. package/dist/geoplateforme.js +23 -21
  71. package/dist/geoplateforme.js.map +1 -1
  72. package/dist/index.d.ts +30 -29
  73. package/dist/index.js +18 -18
  74. package/dist/index.js.map +1 -1
  75. package/dist/isard_bg.wasm +0 -0
  76. package/dist/isard_core_bg.wasm +0 -0
  77. package/dist/isard_points_bg.wasm +0 -0
  78. package/dist/{extrusions.d.ts → layers/extrusions.d.ts} +1 -1
  79. package/dist/{extrusions.js → layers/extrusions.js} +10 -5
  80. package/dist/layers/extrusions.js.map +1 -0
  81. package/dist/{features.d.ts → layers/features.d.ts} +10 -10
  82. package/dist/{features.js → layers/features.js} +44 -45
  83. package/dist/layers/features.js.map +1 -0
  84. package/dist/{glyphs.d.ts → layers/glyphs.d.ts} +6 -6
  85. package/dist/{glyphs.js → layers/glyphs.js} +45 -41
  86. package/dist/layers/glyphs.js.map +1 -0
  87. package/dist/{icons.d.ts → layers/icons.d.ts} +10 -10
  88. package/dist/{icons.js → layers/icons.js} +84 -69
  89. package/dist/layers/icons.js.map +1 -0
  90. package/dist/{layers.d.ts → layers/layers.d.ts} +9 -4
  91. package/dist/{layers.js → layers/layers.js} +35 -31
  92. package/dist/layers/layers.js.map +1 -0
  93. package/dist/{panoramas.d.ts → layers/panoramas.d.ts} +3 -3
  94. package/dist/{panoramas.js → layers/panoramas.js} +54 -43
  95. package/dist/layers/panoramas.js.map +1 -0
  96. package/dist/{pointclouds.d.ts → layers/pointclouds.d.ts} +5 -5
  97. package/dist/{pointclouds.js → layers/pointclouds.js} +26 -34
  98. package/dist/layers/pointclouds.js.map +1 -0
  99. package/dist/{symbols.d.ts → layers/symbols.d.ts} +3 -3
  100. package/dist/{symbols.js → layers/symbols.js} +69 -72
  101. package/dist/layers/symbols.js.map +1 -0
  102. package/dist/map/basemap-layers.d.ts +26 -0
  103. package/dist/map/basemap-layers.js +61 -0
  104. package/dist/map/basemap-layers.js.map +1 -0
  105. package/dist/map/canvas.d.ts +17 -0
  106. package/dist/map/canvas.js +56 -0
  107. package/dist/map/canvas.js.map +1 -0
  108. package/dist/map/checks.d.ts +11 -0
  109. package/dist/map/checks.js +39 -0
  110. package/dist/map/checks.js.map +1 -0
  111. package/dist/map/credits.d.ts +17 -0
  112. package/dist/map/credits.js +34 -0
  113. package/dist/map/credits.js.map +1 -0
  114. package/dist/map/engine-settings.d.ts +15 -0
  115. package/dist/map/engine-settings.js +45 -0
  116. package/dist/map/engine-settings.js.map +1 -0
  117. package/dist/map/engines.d.ts +41 -0
  118. package/dist/map/engines.js +77 -0
  119. package/dist/map/engines.js.map +1 -0
  120. package/dist/map/events.d.ts +14 -0
  121. package/dist/map/events.js +46 -0
  122. package/dist/map/events.js.map +1 -0
  123. package/dist/map/frame-loop.d.ts +61 -0
  124. package/dist/map/frame-loop.js +139 -0
  125. package/dist/map/frame-loop.js.map +1 -0
  126. package/dist/map/hover-pick.d.ts +30 -0
  127. package/dist/map/hover-pick.js +56 -0
  128. package/dist/map/hover-pick.js.map +1 -0
  129. package/dist/map/layer-spec.d.ts +42 -0
  130. package/dist/map/layer-spec.js +34 -0
  131. package/dist/map/layer-spec.js.map +1 -0
  132. package/dist/map/layer-stack.d.ts +36 -0
  133. package/dist/map/layer-stack.js +101 -0
  134. package/dist/map/layer-stack.js.map +1 -0
  135. package/dist/map/overlay-host.d.ts +36 -0
  136. package/dist/map/overlay-host.js +101 -0
  137. package/dist/map/overlay-host.js.map +1 -0
  138. package/dist/map/panorama-host.d.ts +5 -0
  139. package/dist/map/panorama-host.js +32 -0
  140. package/dist/map/panorama-host.js.map +1 -0
  141. package/dist/map/raster-source.d.ts +11 -0
  142. package/dist/map/raster-source.js +26 -0
  143. package/dist/map/raster-source.js.map +1 -0
  144. package/dist/map/symbol-atlases.d.ts +26 -0
  145. package/dist/map/symbol-atlases.js +59 -0
  146. package/dist/map/symbol-atlases.js.map +1 -0
  147. package/dist/map/viewshed.d.ts +5 -0
  148. package/dist/map/viewshed.js +28 -0
  149. package/dist/map/viewshed.js.map +1 -0
  150. package/dist/map/workers.d.ts +46 -0
  151. package/dist/map/workers.js +73 -0
  152. package/dist/map/workers.js.map +1 -0
  153. package/dist/map.d.ts +46 -127
  154. package/dist/map.js +183 -698
  155. package/dist/map.js.map +1 -1
  156. package/dist/projections.d.ts +3 -3
  157. package/dist/projections.js +2 -2
  158. package/dist/projections.js.map +1 -1
  159. package/dist/react/Control.d.ts +11 -0
  160. package/dist/react/Control.js +18 -0
  161. package/dist/react/Control.js.map +1 -0
  162. package/dist/react/CustomLayer.d.ts +11 -0
  163. package/dist/react/CustomLayer.js +30 -0
  164. package/dist/react/CustomLayer.js.map +1 -0
  165. package/dist/react/IsardMap.d.ts +43 -0
  166. package/dist/react/IsardMap.js +146 -0
  167. package/dist/react/IsardMap.js.map +1 -0
  168. package/dist/react/Layer.d.ts +42 -0
  169. package/dist/react/Layer.js +74 -0
  170. package/dist/react/Layer.js.map +1 -0
  171. package/dist/react/Marker.d.ts +24 -0
  172. package/dist/react/Marker.js +53 -0
  173. package/dist/react/Marker.js.map +1 -0
  174. package/dist/react/Panel.d.ts +11 -0
  175. package/dist/react/Panel.js +37 -0
  176. package/dist/react/Panel.js.map +1 -0
  177. package/dist/react/Popup.d.ts +18 -0
  178. package/dist/react/Popup.js +60 -0
  179. package/dist/react/Popup.js.map +1 -0
  180. package/dist/react/Swipe.d.ts +9 -0
  181. package/dist/react/Swipe.js +41 -0
  182. package/dist/react/Swipe.js.map +1 -0
  183. package/dist/react/Viewshed.d.ts +5 -0
  184. package/dist/react/Viewshed.js +28 -0
  185. package/dist/react/Viewshed.js.map +1 -0
  186. package/dist/react/context.d.ts +32 -0
  187. package/dist/react/context.js +20 -0
  188. package/dist/react/context.js.map +1 -0
  189. package/dist/react/index.d.ts +26 -0
  190. package/dist/react/index.js +22 -0
  191. package/dist/react/index.js.map +1 -0
  192. package/dist/settings.d.ts +6 -10
  193. package/dist/settings.js +19 -17
  194. package/dist/settings.js.map +1 -1
  195. package/dist/types.d.ts +8 -8
  196. package/dist/types.js +1 -0
  197. package/dist/types.js.map +1 -1
  198. package/dist/{controls.d.ts → ui/controls.d.ts} +1 -1
  199. package/dist/{controls.js → ui/controls.js} +6 -4
  200. package/dist/ui/controls.js.map +1 -0
  201. package/dist/{interaction.d.ts → ui/interaction.d.ts} +9 -5
  202. package/dist/{interaction.js → ui/interaction.js} +9 -8
  203. package/dist/ui/interaction.js.map +1 -0
  204. package/dist/{overlay.d.ts → ui/overlay.d.ts} +2 -2
  205. package/dist/{overlay.js → ui/overlay.js} +18 -20
  206. package/dist/ui/overlay.js.map +1 -0
  207. package/dist/{style.d.ts → ui/style.d.ts} +1 -1
  208. package/dist/{style.js → ui/style.js} +2 -2
  209. package/dist/ui/style.js.map +1 -0
  210. package/dist/{animation.d.ts → util/animation.d.ts} +9 -5
  211. package/dist/{animation.js → util/animation.js} +6 -6
  212. package/dist/util/animation.js.map +1 -0
  213. package/dist/{color.d.ts → util/color.d.ts} +1 -1
  214. package/dist/{color.js → util/color.js} +14 -16
  215. package/dist/util/color.js.map +1 -0
  216. package/dist/{geo.d.ts → util/geo.d.ts} +6 -6
  217. package/dist/{geo.js → util/geo.js} +12 -12
  218. package/dist/util/geo.js.map +1 -0
  219. package/dist/util/guards.d.ts +7 -0
  220. package/dist/util/guards.js +8 -0
  221. package/dist/util/guards.js.map +1 -0
  222. package/dist/util/lru.js.map +1 -0
  223. package/dist/wasm/isard.d.ts +168 -0
  224. package/dist/wasm/isard.js +146 -0
  225. package/dist/wasm/isard_core.d.ts +144 -0
  226. package/dist/wasm/isard_core.js +122 -0
  227. package/dist/{basemap.worker.d.ts → workers/basemap.worker.d.ts} +17 -7
  228. package/dist/workers/basemap.worker.js +658 -0
  229. package/dist/workers/basemap.worker.js.map +1 -0
  230. package/package.json +24 -1
  231. package/vite.js +1 -1
  232. package/dist/animation.js.map +0 -1
  233. package/dist/basemaps.js.map +0 -1
  234. package/dist/color.js.map +0 -1
  235. package/dist/controls.js.map +0 -1
  236. package/dist/crs.js.map +0 -1
  237. package/dist/decoders.js.map +0 -1
  238. package/dist/extrusions.js.map +0 -1
  239. package/dist/features.js.map +0 -1
  240. package/dist/geo.js.map +0 -1
  241. package/dist/glyphs.js.map +0 -1
  242. package/dist/gpx.js.map +0 -1
  243. package/dist/grid.js.map +0 -1
  244. package/dist/icons.js.map +0 -1
  245. package/dist/interaction.js.map +0 -1
  246. package/dist/kml.js.map +0 -1
  247. package/dist/layers.js.map +0 -1
  248. package/dist/loader.js.map +0 -1
  249. package/dist/lru.js.map +0 -1
  250. package/dist/mvt.js.map +0 -1
  251. package/dist/overlay.js.map +0 -1
  252. package/dist/panoramas.js.map +0 -1
  253. package/dist/pmtiles.js.map +0 -1
  254. package/dist/pointclouds.js.map +0 -1
  255. package/dist/protocol.js +0 -2
  256. package/dist/protocol.js.map +0 -1
  257. package/dist/requests.js.map +0 -1
  258. package/dist/resample.js.map +0 -1
  259. package/dist/style.js.map +0 -1
  260. package/dist/symbols.js.map +0 -1
  261. package/dist/terrain.js.map +0 -1
  262. package/dist/topojson.js.map +0 -1
  263. package/dist/vectorstyle.js.map +0 -1
  264. package/dist/vectortiles.js.map +0 -1
  265. package/dist/wmts.js.map +0 -1
  266. package/dist/xml.js.map +0 -1
  267. /package/dist/{lru.d.ts → util/lru.d.ts} +0 -0
  268. /package/dist/{lru.js → util/lru.js} +0 -0
@@ -0,0 +1,41 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /** `<Swipe>`: the `<Layer>` in it on one side of a vertical line only */
3
+ import { useEffect, useMemo, useRef } from 'react';
4
+ import { defined, SwipeContext, useMap } from "./context.js";
5
+ /** The `<Layer>` in it shown on one side of a vertical line only, at `position` CSS pixels from the left */
6
+ export const Swipe = (props) => {
7
+ const map = useMap();
8
+ const latest = useRef(props);
9
+ const { position, side } = props;
10
+ const layers = useMemo(() => new Set(), []);
11
+ latest.current = props;
12
+ const group = useMemo(() => {
13
+ if (!map)
14
+ return undefined;
15
+ const apply = () => {
16
+ const { position, side } = latest.current;
17
+ map.setSwipe(layers.size > 0 ? { position, layers: [...layers], ...defined({ side }) } : undefined);
18
+ };
19
+ return {
20
+ set: (layer) => {
21
+ layers.add(layer);
22
+ apply();
23
+ },
24
+ unset: (layer) => {
25
+ layers.delete(layer);
26
+ apply();
27
+ },
28
+ };
29
+ }, [map, layers]);
30
+ // The line's position and side sent to the map when they change (the layers in it come and go through the group)
31
+ useEffect(() => {
32
+ if (map && layers.size > 0)
33
+ map.setSwipe({ position, layers: [...layers], ...defined({ side }) });
34
+ }, [map, layers, position, side]);
35
+ // The swipe taken off the map when unmounted
36
+ useEffect(() => () => {
37
+ map?.setSwipe(undefined);
38
+ }, [map]);
39
+ return _jsx(SwipeContext.Provider, { value: group, children: props.children });
40
+ };
41
+ //# sourceMappingURL=Swipe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Swipe.js","sourceRoot":"","sources":["../../src/react/Swipe.tsx"],"names":[],"mappings":";AAAA,yEAAyE;AAEzE,OAAO,EAAkB,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAGnE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAmB,MAAM,EAAE,MAAM,cAAc,CAAC;AAO9E,4GAA4G;AAC5G,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,KAAiB,EAAa,EAAE;IACpD,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;IACrB,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7B,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;IACjC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,GAAG,EAAe,EAAE,EAAE,CAAC,CAAC;IAEzD,MAAM,CAAC,OAAO,GAAG,KAAK,CAAC;IAEvB,MAAM,KAAK,GAAG,OAAO,CAAyB,GAAG,EAAE;QACjD,IAAI,CAAC,GAAG;YAAE,OAAO,SAAS,CAAC;QAE3B,MAAM,KAAK,GAAG,GAAG,EAAE;YACjB,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC;YAE1C,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC,EAAE,GAAG,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QACtG,CAAC,CAAC;QAEF,OAAO;YACL,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE;gBACb,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBAClB,KAAK,EAAE,CAAC;YACV,CAAC;YACD,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE;gBACf,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACrB,KAAK,EAAE,CAAC;YACV,CAAC;SACF,CAAC;IACJ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC;IAElB,iHAAiH;IACjH,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,GAAG,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC;YAAE,GAAG,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC,EAAE,GAAG,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;IACpG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;IAClC,6CAA6C;IAC7C,SAAS,CACP,GAAG,EAAE,CAAC,GAAG,EAAE;QACT,GAAG,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC3B,CAAC,EACD,CAAC,GAAG,CAAC,CACN,CAAC;IAEF,OAAO,KAAC,YAAY,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YAAG,KAAK,CAAC,QAAQ,GAAyB,CAAC;AACvF,CAAC,CAAC","sourcesContent":["/** `<Swipe>`: the `<Layer>` in it on one side of a vertical line only */\n\nimport { type ReactNode, useEffect, useMemo, useRef } from 'react';\nimport type { Layer as LayerHandle } from '../layers/layers.ts';\nimport type { SwipeOptions } from '../types.ts';\nimport { defined, SwipeContext, type SwipeGroup, useMap } from './context.ts';\n\nexport interface SwipeProps extends Omit<SwipeOptions, 'layers'> {\n /** The `<Layer>` shown on one side of the line only */\n children?: ReactNode;\n}\n\n/** The `<Layer>` in it shown on one side of a vertical line only, at `position` CSS pixels from the left */\nexport const Swipe = (props: SwipeProps): ReactNode => {\n const map = useMap();\n const latest = useRef(props);\n const { position, side } = props;\n const layers = useMemo(() => new Set<LayerHandle>(), []);\n\n latest.current = props;\n\n const group = useMemo<SwipeGroup | undefined>(() => {\n if (!map) return undefined;\n\n const apply = () => {\n const { position, side } = latest.current;\n\n map.setSwipe(layers.size > 0 ? { position, layers: [...layers], ...defined({ side }) } : undefined);\n };\n\n return {\n set: (layer) => {\n layers.add(layer);\n apply();\n },\n unset: (layer) => {\n layers.delete(layer);\n apply();\n },\n };\n }, [map, layers]);\n\n // The line's position and side sent to the map when they change (the layers in it come and go through the group)\n useEffect(() => {\n if (map && layers.size > 0) map.setSwipe({ position, layers: [...layers], ...defined({ side }) });\n }, [map, layers, position, side]);\n // The swipe taken off the map when unmounted\n useEffect(\n () => () => {\n map?.setSwipe(undefined);\n },\n [map],\n );\n\n return <SwipeContext.Provider value={group}>{props.children}</SwipeContext.Provider>;\n};\n"]}
@@ -0,0 +1,5 @@
1
+ /** `<Viewshed>`: an observer's viewshed, several drawn together */
2
+ import { type ReactNode } from 'react';
3
+ import type { ViewshedOptions } from '../types.ts';
4
+ /** An observer's viewshed; several `<Viewshed>` are drawn together */
5
+ export declare const Viewshed: (props: ViewshedOptions) => ReactNode;
@@ -0,0 +1,28 @@
1
+ /** `<Viewshed>`: an observer's viewshed, several drawn together */
2
+ import { useContext, useEffect, useMemo } from 'react';
3
+ import { MapContext } from "./context.js";
4
+ /** An observer's viewshed; several `<Viewshed>` are drawn together */
5
+ export const Viewshed = (props) => {
6
+ const binding = useContext(MapContext);
7
+ const key = useMemo(() => ({}), []);
8
+ // Numbers, strings and the position: compared by value
9
+ const options = JSON.stringify(props);
10
+ // Its observer taken off the map's viewsheds when unmounted
11
+ useEffect(() => {
12
+ if (!binding)
13
+ return;
14
+ return () => {
15
+ binding.viewsheds.delete(key);
16
+ binding.applyViewsheds();
17
+ };
18
+ }, [binding, key]);
19
+ // Its observer set among the map's viewsheds when its options change (compared by value)
20
+ useEffect(() => {
21
+ if (!binding)
22
+ return;
23
+ binding.viewsheds.set(key, JSON.parse(options));
24
+ binding.applyViewsheds();
25
+ }, [binding, key, options]);
26
+ return null;
27
+ };
28
+ //# sourceMappingURL=Viewshed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Viewshed.js","sourceRoot":"","sources":["../../src/react/Viewshed.tsx"],"names":[],"mappings":"AAAA,mEAAmE;AAEnE,OAAO,EAAkB,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAEvE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,sEAAsE;AACtE,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,KAAsB,EAAa,EAAE;IAC5D,MAAM,OAAO,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;IACvC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IACpC,uDAAuD;IACvD,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAEtC,4DAA4D;IAC5D,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,OAAO;YAAE,OAAO;QAErB,OAAO,GAAG,EAAE;YACV,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC9B,OAAO,CAAC,cAAc,EAAE,CAAC;QAC3B,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;IAEnB,yFAAyF;IACzF,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAoB,CAAC,CAAC;QACnE,OAAO,CAAC,cAAc,EAAE,CAAC;IAC3B,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;IAE5B,OAAO,IAAI,CAAC;AACd,CAAC,CAAC","sourcesContent":["/** `<Viewshed>`: an observer's viewshed, several drawn together */\n\nimport { type ReactNode, useContext, useEffect, useMemo } from 'react';\nimport type { ViewshedOptions } from '../types.ts';\nimport { MapContext } from './context.ts';\n\n/** An observer's viewshed; several `<Viewshed>` are drawn together */\nexport const Viewshed = (props: ViewshedOptions): ReactNode => {\n const binding = useContext(MapContext);\n const key = useMemo(() => ({}), []);\n // Numbers, strings and the position: compared by value\n const options = JSON.stringify(props);\n\n // Its observer taken off the map's viewsheds when unmounted\n useEffect(() => {\n if (!binding) return;\n\n return () => {\n binding.viewsheds.delete(key);\n binding.applyViewsheds();\n };\n }, [binding, key]);\n\n // Its observer set among the map's viewsheds when its options change (compared by value)\n useEffect(() => {\n if (!binding) return;\n binding.viewsheds.set(key, JSON.parse(options) as ViewshedOptions);\n binding.applyViewsheds();\n }, [binding, key, options]);\n\n return null;\n};\n"]}
@@ -0,0 +1,32 @@
1
+ /** What the components of a map share: the map, the order of their layers, the viewsheds, the swipe and the marker
2
+ * around; the hooks */
3
+ import type { LayerOrder } from '../bind/layers.ts';
4
+ import type { Layer as LayerHandle } from '../layers/layers.ts';
5
+ import type { GeoMap } from '../map.ts';
6
+ import type { LonLat, MapEvents, ViewshedOptions } from '../types.ts';
7
+ import type { Marker as MarkerHandle } from '../ui/overlay.ts';
8
+ export interface Binding {
9
+ map: GeoMap;
10
+ order: LayerOrder;
11
+ /** The observers of the `<Viewshed>` components, set on the map together */
12
+ viewsheds: Map<object, ViewshedOptions>;
13
+ applyViewsheds(): void;
14
+ }
15
+ export declare const MapContext: import("react").Context<Binding | undefined>;
16
+ /** The layers of a `<Swipe>` around, its `<Layer>` children joining it */
17
+ export interface SwipeGroup {
18
+ set(layer: LayerHandle): void;
19
+ unset(layer: LayerHandle): void;
20
+ }
21
+ export declare const SwipeContext: import("react").Context<SwipeGroup | undefined>;
22
+ /** The marker of a `<Marker>` around and its position (a `<Popup>` in it opens on its click, at that position) */
23
+ export declare const MarkerContext: import("react").Context<{
24
+ marker: MarkerHandle;
25
+ lonLat: LonLat;
26
+ } | undefined>;
27
+ /** The map of the `<IsardMap>` around, once created (undefined before) */
28
+ export declare const useMap: () => GeoMap | undefined;
29
+ /** Listens to an event of the map around while the component is mounted; the listener may change at each render */
30
+ export declare const useMapEvent: <K extends keyof MapEvents>(type: K, listener: (event: MapEvents[K]) => void) => void;
31
+ /** The entries of an object whose value is defined (`exactOptionalPropertyTypes`) */
32
+ export declare const defined: <T extends object>(object: T) => { [K in keyof T]?: Exclude<T[K], undefined>; };
@@ -0,0 +1,20 @@
1
+ /** What the components of a map share: the map, the order of their layers, the viewsheds, the swipe and the marker
2
+ * around; the hooks */
3
+ import { createContext, useContext, useEffect, useRef } from 'react';
4
+ export const MapContext = createContext(undefined);
5
+ export const SwipeContext = createContext(undefined);
6
+ /** The marker of a `<Marker>` around and its position (a `<Popup>` in it opens on its click, at that position) */
7
+ export const MarkerContext = createContext(undefined);
8
+ /** The map of the `<IsardMap>` around, once created (undefined before) */
9
+ export const useMap = () => useContext(MapContext)?.map;
10
+ /** Listens to an event of the map around while the component is mounted; the listener may change at each render */
11
+ export const useMapEvent = (type, listener) => {
12
+ const map = useMap();
13
+ const latest = useRef(listener);
14
+ latest.current = listener;
15
+ // Listening while mounted, to the listener of the last render; stops when unmounted or the map changes
16
+ useEffect(() => map?.on(type, (event) => latest.current(event)), [map, type]);
17
+ };
18
+ /** The entries of an object whose value is defined (`exactOptionalPropertyTypes`) */
19
+ export const defined = (object) => Object.fromEntries(Object.entries(object).filter(([, value]) => value !== undefined));
20
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/react/context.ts"],"names":[],"mappings":"AAAA;uBACuB;AAEvB,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAerE,MAAM,CAAC,MAAM,UAAU,GAAG,aAAa,CAAsB,SAAS,CAAC,CAAC;AAQxE,MAAM,CAAC,MAAM,YAAY,GAAG,aAAa,CAAyB,SAAS,CAAC,CAAC;AAE7E,kHAAkH;AAClH,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,CAAuD,SAAS,CAAC,CAAC;AAE5G,0EAA0E;AAC1E,MAAM,CAAC,MAAM,MAAM,GAAG,GAAuB,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,GAAG,CAAC;AAE5E,mHAAmH;AACnH,MAAM,CAAC,MAAM,WAAW,GAAG,CAA4B,IAAO,EAAE,QAAuC,EAAQ,EAAE;IAC/G,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;IACrB,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAEhC,MAAM,CAAC,OAAO,GAAG,QAAQ,CAAC;IAC1B,uGAAuG;IACvG,SAAS,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;AAChF,CAAC,CAAC;AAEF,qFAAqF;AACrF,MAAM,CAAC,MAAM,OAAO,GAAG,CAAmB,MAAS,EAAiD,EAAE,CACpG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC,CAEnF,CAAC","sourcesContent":["/** What the components of a map share: the map, the order of their layers, the viewsheds, the swipe and the marker\n * around; the hooks */\n\nimport { createContext, useContext, useEffect, useRef } from 'react';\nimport type { LayerOrder } from '../bind/layers.ts';\nimport type { Layer as LayerHandle } from '../layers/layers.ts';\nimport type { GeoMap } from '../map.ts';\nimport type { LonLat, MapEvents, ViewshedOptions } from '../types.ts';\nimport type { Marker as MarkerHandle } from '../ui/overlay.ts';\n\nexport interface Binding {\n map: GeoMap;\n order: LayerOrder;\n /** The observers of the `<Viewshed>` components, set on the map together */\n viewsheds: Map<object, ViewshedOptions>;\n applyViewsheds(): void;\n}\n\nexport const MapContext = createContext<Binding | undefined>(undefined);\n\n/** The layers of a `<Swipe>` around, its `<Layer>` children joining it */\nexport interface SwipeGroup {\n set(layer: LayerHandle): void;\n unset(layer: LayerHandle): void;\n}\n\nexport const SwipeContext = createContext<SwipeGroup | undefined>(undefined);\n\n/** The marker of a `<Marker>` around and its position (a `<Popup>` in it opens on its click, at that position) */\nexport const MarkerContext = createContext<{ marker: MarkerHandle; lonLat: LonLat } | undefined>(undefined);\n\n/** The map of the `<IsardMap>` around, once created (undefined before) */\nexport const useMap = (): GeoMap | undefined => useContext(MapContext)?.map;\n\n/** Listens to an event of the map around while the component is mounted; the listener may change at each render */\nexport const useMapEvent = <K extends keyof MapEvents>(type: K, listener: (event: MapEvents[K]) => void): void => {\n const map = useMap();\n const latest = useRef(listener);\n\n latest.current = listener;\n // Listening while mounted, to the listener of the last render; stops when unmounted or the map changes\n useEffect(() => map?.on(type, (event) => latest.current(event)), [map, type]);\n};\n\n/** The entries of an object whose value is defined (`exactOptionalPropertyTypes`) */\nexport const defined = <T extends object>(object: T): { [K in keyof T]?: Exclude<T[K], undefined> } =>\n Object.fromEntries(Object.entries(object).filter(([, value]) => value !== undefined)) as {\n [K in keyof T]?: Exclude<T[K], undefined>;\n };\n"]}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Isard in React: the map, its layers, markers, popups, panels and effects as components, created when they mount,
3
+ * updated by the least their props need and removed when they unmount.
4
+ *
5
+ * ```tsx
6
+ * <IsardMap preset="ign-3d" center={[2.35, 48.85]} zoom={15} style={{ height: 400 }}>
7
+ * <Layer type="lines" data={routes} color="#0057b8" width={3} />
8
+ * <Marker lonLat={[2.35, 48.85]}><Popup>Here</Popup></Marker>
9
+ * </IsardMap>
10
+ * ```
11
+ */
12
+ export type { Layer as LayerHandle } from '../layers/layers.ts';
13
+ export type { GeoMap, LayerSpec } from '../map.ts';
14
+ export type { LonLat } from '../types.ts';
15
+ export type { Marker as MarkerHandle, Panel as PanelHandle, Popup as PopupHandle } from '../ui/overlay.ts';
16
+ export type { Camera } from '../wasm/isard.js';
17
+ export { Control, type ControlProps } from './Control.tsx';
18
+ export { CustomLayer, type CustomLayerProps } from './CustomLayer.tsx';
19
+ export { useMap, useMapEvent } from './context.ts';
20
+ export { IsardMap, type IsardMapProps, type MapEventProps } from './IsardMap.tsx';
21
+ export { Layer, type LayerHandles, type LayerProps, type LayerType } from './Layer.tsx';
22
+ export { Marker, type MarkerProps } from './Marker.tsx';
23
+ export { Panel, type PanelProps } from './Panel.tsx';
24
+ export { Popup, type PopupProps } from './Popup.tsx';
25
+ export { Swipe, type SwipeProps } from './Swipe.tsx';
26
+ export { Viewshed } from './Viewshed.tsx';
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Isard in React: the map, its layers, markers, popups, panels and effects as components, created when they mount,
3
+ * updated by the least their props need and removed when they unmount.
4
+ *
5
+ * ```tsx
6
+ * <IsardMap preset="ign-3d" center={[2.35, 48.85]} zoom={15} style={{ height: 400 }}>
7
+ * <Layer type="lines" data={routes} color="#0057b8" width={3} />
8
+ * <Marker lonLat={[2.35, 48.85]}><Popup>Here</Popup></Marker>
9
+ * </IsardMap>
10
+ * ```
11
+ */
12
+ export { Control } from "./Control.js";
13
+ export { CustomLayer } from "./CustomLayer.js";
14
+ export { useMap, useMapEvent } from "./context.js";
15
+ export { IsardMap } from "./IsardMap.js";
16
+ export { Layer } from "./Layer.js";
17
+ export { Marker } from "./Marker.js";
18
+ export { Panel } from "./Panel.js";
19
+ export { Popup } from "./Popup.js";
20
+ export { Swipe } from "./Swipe.js";
21
+ export { Viewshed } from "./Viewshed.js";
22
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAOH,OAAO,EAAE,OAAO,EAAqB,MAAM,cAAe,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAyB,MAAM,kBAAmB,CAAC;AACvE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,QAAQ,EAA0C,MAAM,eAAgB,CAAC;AAClF,OAAO,EAAE,KAAK,EAAsD,MAAM,YAAa,CAAC;AACxF,OAAO,EAAE,MAAM,EAAoB,MAAM,aAAc,CAAC;AACxD,OAAO,EAAE,KAAK,EAAmB,MAAM,YAAa,CAAC;AACrD,OAAO,EAAE,KAAK,EAAmB,MAAM,YAAa,CAAC;AACrD,OAAO,EAAE,KAAK,EAAmB,MAAM,YAAa,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAgB,CAAC","sourcesContent":["/**\n * Isard in React: the map, its layers, markers, popups, panels and effects as components, created when they mount,\n * updated by the least their props need and removed when they unmount.\n *\n * ```tsx\n * <IsardMap preset=\"ign-3d\" center={[2.35, 48.85]} zoom={15} style={{ height: 400 }}>\n * <Layer type=\"lines\" data={routes} color=\"#0057b8\" width={3} />\n * <Marker lonLat={[2.35, 48.85]}><Popup>Here</Popup></Marker>\n * </IsardMap>\n * ```\n */\n\nexport type { Layer as LayerHandle } from '../layers/layers.ts';\nexport type { GeoMap, LayerSpec } from '../map.ts';\nexport type { LonLat } from '../types.ts';\nexport type { Marker as MarkerHandle, Panel as PanelHandle, Popup as PopupHandle } from '../ui/overlay.ts';\nexport type { Camera } from '../wasm/isard.js';\nexport { Control, type ControlProps } from './Control.tsx';\nexport { CustomLayer, type CustomLayerProps } from './CustomLayer.tsx';\nexport { useMap, useMapEvent } from './context.ts';\nexport { IsardMap, type IsardMapProps, type MapEventProps } from './IsardMap.tsx';\nexport { Layer, type LayerHandles, type LayerProps, type LayerType } from './Layer.tsx';\nexport { Marker, type MarkerProps } from './Marker.tsx';\nexport { Panel, type PanelProps } from './Panel.tsx';\nexport { Popup, type PopupProps } from './Popup.tsx';\nexport { Swipe, type SwipeProps } from './Swipe.tsx';\nexport { Viewshed } from './Viewshed.tsx';\n"]}
@@ -1,4 +1,4 @@
1
- import type { PngEncoding } from './terrain.ts';
1
+ import type { PngEncoding } from './basemap/terrain.ts';
2
2
  import type { AtmosphereOptions, BodyOptions, CelestialBody, LoadingMode, TerrainModel, TerrainOptions } from './types.ts';
3
3
  /** Decodes the relief tiles of a URL for the engine: 256 × 256 altitudes, null where there is no tile */
4
4
  export type TerrainLoader = (z: number, x: number, y: number, signal: AbortSignal) => Promise<Float32Array | null>;
@@ -25,15 +25,11 @@ export interface Settings {
25
25
  globeColor: [r: number, g: number, b: number];
26
26
  }
27
27
  /** A body from the option, its defaults filled in */
28
- export declare function bodySettings(body: CelestialBody | undefined): Required<BodyOptions>;
28
+ export declare const bodySettings: (body: CelestialBody | undefined) => Required<BodyOptions>;
29
29
  /** The halo of an atmosphere for the engine (RGB 0-1 and its strength, the color's alpha): undefined for none */
30
- export declare function haloSettings(atmosphere: boolean | string): Float32Array | undefined;
31
- /** Relief settings from the option: undefined when off. On the Earth the Terrain Tiles by default (worldwide,
32
- * Terrarium PNGs decoded by `terrainLoader`) or the IGN terrain model (France, raised by the geoid); NASA's on the Moon
33
- * and Mars; an ArcGIS image service asked for in the body's Mercator. `terrainLoader`: the loader of PNG tiles in an
34
- * encoding, the same for the same tiles (the engine keeps its tiles when only the exaggeration changes) */
35
- export declare function terrainSettings(terrain: boolean | TerrainModel | TerrainOptions | undefined, body: CelestialBody | undefined, radius: number, terrainLoader: (url: string, encoding: PngEncoding, floor?: number) => TerrainLoader): Settings['terrain'];
30
+ export declare const haloSettings: (atmosphere: boolean | string) => Float32Array | undefined;
31
+ export declare const terrainSettings: (terrain: boolean | TerrainModel | TerrainOptions | undefined, body: CelestialBody | undefined, radius: number, terrainLoader: (url: string, encoding: PngEncoding, floor?: number) => TerrainLoader) => Settings["terrain"];
36
32
  /** Sky settings for the engine: colors (RGB 0-1) and blends, MapLibre's defaults */
37
- export declare function atmosphereSettings(options: AtmosphereOptions | undefined): Float32Array | undefined;
33
+ export declare const atmosphereSettings: (options: AtmosphereOptions | undefined) => Float32Array | undefined;
38
34
  /** A CSS color to RGB 0-1 (its alpha dropped); black if unknown */
39
- export declare function rgb(color: string): [r: number, g: number, b: number];
35
+ export declare const rgb: (color: string) => [r: number, g: number, b: number];
package/dist/settings.js CHANGED
@@ -2,8 +2,8 @@
2
2
  * The settings of a map's engine from its options: the body, its halo, its relief, the sky. Kept by the map and
3
3
  * replayed on a new engine (after a context loss, or on the engine with 3D Tiles).
4
4
  */
5
- import { BODY_TERRAINS, IGN_ATTRIBUTION, IMAGE_SERVER, imageServerTerrain, TERRAIN_TILES, TERRAIN_TILES_ATTRIBUTION, TERRAIN_URL, } from "./basemaps.js";
6
- import { parseCssColor } from "./color.js";
5
+ import { BODY_TERRAINS, IGN_ATTRIBUTION, IMAGE_SERVER, imageServerTerrain, TERRAIN_TILES, TERRAIN_TILES_ATTRIBUTION, TERRAIN_URL, } from "./basemap/basemaps.js";
6
+ import { parseCssColor } from "./util/color.js";
7
7
  /** The named bodies; a body's `color` is that of its globe under the tiles (the Earth's follows its basemap), its
8
8
  * `relief` the range of its ground (the Earth's dry land, from the Dead Sea to Everest). Mars: the sphere of its
9
9
  * equatorial radius (its data take planetocentric latitudes), a faint butterscotch halo of dust */
@@ -21,31 +21,33 @@ const BODIES = {
21
21
  /** The Earth's halo, RGB 0-1 and its strength: what `atmosphere: true` draws */
22
22
  const EARTH_HALO = Float32Array.of(0.42, 0.66, 1, 1);
23
23
  /** A body from the option, its defaults filled in */
24
- export function bodySettings(body) {
24
+ export const bodySettings = (body) => {
25
25
  if (body === undefined || typeof body === 'string')
26
26
  return BODIES[body ?? 'earth'];
27
27
  const relief = [-0.01 * body.radius, 0.01 * body.radius];
28
28
  return { flattening: 0, atmosphere: false, color: '#808080', relief, ...body };
29
- }
29
+ };
30
30
  /** The halo of an atmosphere for the engine (RGB 0-1 and its strength, the color's alpha): undefined for none */
31
- export function haloSettings(atmosphere) {
31
+ export const haloSettings = (atmosphere) => {
32
32
  if (atmosphere === true)
33
33
  return EARTH_HALO;
34
34
  const color = atmosphere === false ? undefined : parseCssColor(atmosphere);
35
35
  return color && Float32Array.from(color);
36
- }
36
+ };
37
37
  /** Relief settings from the option: undefined when off. On the Earth the Terrain Tiles by default (worldwide,
38
38
  * Terrarium PNGs decoded by `terrainLoader`) or the IGN terrain model (France, raised by the geoid); NASA's on the Moon
39
39
  * and Mars; an ArcGIS image service asked for in the body's Mercator. `terrainLoader`: the loader of PNG tiles in an
40
40
  * encoding, the same for the same tiles (the engine keeps its tiles when only the exaggeration changes) */
41
- export function terrainSettings(terrain, body, radius, terrainLoader) {
41
+ /** The relief options of the option on */
42
+ const terrainOptions = (terrain) => {
43
+ if (typeof terrain === 'string')
44
+ return { model: terrain };
45
+ return terrain === true ? {} : terrain;
46
+ };
47
+ export const terrainSettings = (terrain, body, radius, terrainLoader) => {
42
48
  if (!terrain)
43
49
  return undefined;
44
- let options = {};
45
- if (typeof terrain === 'string')
46
- options = { model: terrain };
47
- else if (terrain !== true)
48
- options = terrain;
50
+ const options = terrainOptions(terrain);
49
51
  const earth = (body ?? 'earth') === 'earth';
50
52
  const exaggeration = options.exaggeration ?? 1;
51
53
  if (options.url === undefined && earth) {
@@ -82,9 +84,9 @@ export function terrainSettings(terrain, body, radius, terrainLoader) {
82
84
  // NASA's credits for its models
83
85
  ...(options.url === undefined && preset ? { attribution: preset.attribution } : {}),
84
86
  };
85
- }
87
+ };
86
88
  /** Sky settings for the engine: colors (RGB 0-1) and blends, MapLibre's defaults */
87
- export function atmosphereSettings(options) {
89
+ export const atmosphereSettings = (options) => {
88
90
  if (!options)
89
91
  return undefined;
90
92
  return Float32Array.from([
@@ -95,10 +97,10 @@ export function atmosphereSettings(options) {
95
97
  options.horizonFogBlend ?? 0.7,
96
98
  options.fogGroundBlend ?? 0.4,
97
99
  ]);
98
- }
100
+ };
99
101
  /** A CSS color to RGB 0-1 (its alpha dropped); black if unknown */
100
- export function rgb(color) {
102
+ export const rgb = (color) => {
101
103
  const [r, g, b] = parseCssColor(color) ?? [0, 0, 0, 1];
102
104
  return [r, g, b];
103
- }
105
+ };
104
106
  //# sourceMappingURL=settings.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACL,aAAa,EACb,eAAe,EACf,YAAY,EACZ,kBAAkB,EAClB,aAAa,EACb,yBAAyB,EACzB,WAAW,GACZ,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAuC3C;;mGAEmG;AACnG,MAAM,MAAM,GAAuE;IACjF,KAAK,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,GAAG,aAAa,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE;IACnH,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE;IACrG,IAAI,EAAE;QACJ,MAAM,EAAE,OAAO;QACf,UAAU,EAAE,CAAC;QACb,UAAU,EAAE,0BAA0B;QACtC,KAAK,EAAE,SAAS;QAChB,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC;KACvB;CACF,CAAC;AAEF,gFAAgF;AAChF,MAAM,UAAU,GAAG,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAErD,qDAAqD;AACrD,MAAM,UAAU,YAAY,CAAC,IAA+B;IAC1D,IAAI,IAAI,KAAK,SAAS,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC,IAAI,IAAI,OAAO,CAAC,CAAC;IACnF,MAAM,MAAM,GAAqB,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3E,OAAO,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,CAAC;AACjF,CAAC;AAED,iHAAiH;AACjH,MAAM,UAAU,YAAY,CAAC,UAA4B;IACvD,IAAI,UAAU,KAAK,IAAI;QAAE,OAAO,UAAU,CAAC;IAC3C,MAAM,KAAK,GAAG,UAAU,KAAK,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IAC3E,OAAO,KAAK,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3C,CAAC;AAED;;;2GAG2G;AAC3G,MAAM,UAAU,eAAe,CAC7B,OAA4D,EAC5D,IAA+B,EAC/B,MAAc,EACd,aAAoF;IAEpF,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAC/B,IAAI,OAAO,GAAmB,EAAE,CAAC;IACjC,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;SACzD,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,GAAG,OAAO,CAAC;IAC7C,MAAM,KAAK,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,KAAK,OAAO,CAAC;IAC5C,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,CAAC,CAAC;IAC/C,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS,IAAI,KAAK,EAAE,CAAC;QACvC,IAAI,OAAO,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;YAC5B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC;YACpC,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,CAAC;QACjH,CAAC;QACD,OAAO;YACL,GAAG,EAAE,aAAa,CAAC,GAAG;YACtB,YAAY;YACZ,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,aAAa,CAAC,OAAO;YACjD,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,KAAK;YAC7B,0FAA0F;YAC1F,MAAM,EAAE,aAAa,CAAC,aAAa,CAAC,GAAG,EAAE,WAAW,EAAE,CAAC,CAAC;YACxD,WAAW,EAAE,yBAAyB;SACvC,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACpF,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,MAAM,EAAE,GAAG,CAAC;IACvC,IAAI,GAAG,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IACrF,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,SAAS,CAAC;IAC/C,iGAAiG;IACjG,IACE,QAAQ,KAAK,SAAS;QACtB,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAC1F,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,eAAe,QAAQ,8DAA8D,GAAG,GAAG,CAAC,CAAC;IAC/G,CAAC;IACD,OAAO;QACL,GAAG,EAAE,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG;QAC1E,YAAY;QACZ,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,KAAK,SAAS,IAAI,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QACvF,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,KAAK;QAC7B,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,GAAG,EAAE,QAAQ,CAAC,EAAE,CAAC;QAC3E,gCAAgC;QAChC,GAAG,CAAC,OAAO,CAAC,GAAG,KAAK,SAAS,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACpF,CAAC;AACJ,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,kBAAkB,CAAC,OAAsC;IACvE,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAC/B,OAAO,YAAY,CAAC,IAAI,CAAC;QACvB,GAAG,GAAG,CAAC,OAAO,CAAC,QAAQ,IAAI,SAAS,CAAC;QACrC,GAAG,GAAG,CAAC,OAAO,CAAC,YAAY,IAAI,SAAS,CAAC;QACzC,GAAG,GAAG,CAAC,OAAO,CAAC,QAAQ,IAAI,SAAS,CAAC;QACrC,OAAO,CAAC,eAAe,IAAI,GAAG;QAC9B,OAAO,CAAC,eAAe,IAAI,GAAG;QAC9B,OAAO,CAAC,cAAc,IAAI,GAAG;KAC9B,CAAC,CAAC;AACL,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,GAAG,CAAC,KAAa;IAC/B,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACvD,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACnB,CAAC","sourcesContent":["/**\n * The settings of a map's engine from its options: the body, its halo, its relief, the sky. Kept by the map and\n * replayed on a new engine (after a context loss, or on the engine with 3D Tiles).\n */\nimport {\n BODY_TERRAINS,\n IGN_ATTRIBUTION,\n IMAGE_SERVER,\n imageServerTerrain,\n TERRAIN_TILES,\n TERRAIN_TILES_ATTRIBUTION,\n TERRAIN_URL,\n} from './basemaps.ts';\nimport { parseCssColor } from './color.ts';\nimport type { PngEncoding } from './terrain.ts';\nimport type {\n AtmosphereOptions,\n BodyOptions,\n CelestialBody,\n LoadingMode,\n TerrainModel,\n TerrainOptions,\n} from './types.ts';\n\n/** Decodes the relief tiles of a URL for the engine: 256 × 256 altitudes, null where there is no tile */\nexport type TerrainLoader = (z: number, x: number, y: number, signal: AbortSignal) => Promise<Float32Array | null>;\n\n/** Settings replayed on a new engine after a WebGL context loss */\nexport interface Settings {\n body: Required<BodyOptions>;\n zoomRange: [min: number, max: number];\n maxPitch: number;\n globe: boolean;\n sky: boolean;\n atmosphere: Float32Array | undefined;\n terrain:\n | {\n url: string;\n exaggeration: number;\n maxZoom: number;\n geoid: boolean;\n /** Decodes the tiles of `url` for the engine (an encoding other than raw floats) */\n loader?: TerrainLoader;\n /** Credits of the model */\n attribution?: string;\n }\n | undefined;\n loading: LoadingMode;\n background: [r: number, g: number, b: number];\n globeColor: [r: number, g: number, b: number];\n}\n\n/** The named bodies; a body's `color` is that of its globe under the tiles (the Earth's follows its basemap), its\n * `relief` the range of its ground (the Earth's dry land, from the Dead Sea to Everest). Mars: the sphere of its\n * equatorial radius (its data take planetocentric latitudes), a faint butterscotch halo of dust */\nconst BODIES: Record<Exclude<CelestialBody, BodyOptions>, Required<BodyOptions>> = {\n earth: { radius: 6378137, flattening: 1 / 298.257223563, atmosphere: true, color: '#cacaca', relief: [-450, 8900] },\n moon: { radius: 1737400, flattening: 0, atmosphere: false, color: '#77756f', relief: [-9200, 10800] },\n mars: {\n radius: 3396190,\n flattening: 0,\n atmosphere: 'rgba(232, 168, 120, 0.6)',\n color: '#b5714a',\n relief: [-8300, 21300],\n },\n};\n\n/** The Earth's halo, RGB 0-1 and its strength: what `atmosphere: true` draws */\nconst EARTH_HALO = Float32Array.of(0.42, 0.66, 1, 1);\n\n/** A body from the option, its defaults filled in */\nexport function bodySettings(body: CelestialBody | undefined): Required<BodyOptions> {\n if (body === undefined || typeof body === 'string') return BODIES[body ?? 'earth'];\n const relief: [number, number] = [-0.01 * body.radius, 0.01 * body.radius];\n return { flattening: 0, atmosphere: false, color: '#808080', relief, ...body };\n}\n\n/** The halo of an atmosphere for the engine (RGB 0-1 and its strength, the color's alpha): undefined for none */\nexport function haloSettings(atmosphere: boolean | string): Float32Array | undefined {\n if (atmosphere === true) return EARTH_HALO;\n const color = atmosphere === false ? undefined : parseCssColor(atmosphere);\n return color && Float32Array.from(color);\n}\n\n/** Relief settings from the option: undefined when off. On the Earth the Terrain Tiles by default (worldwide,\n * Terrarium PNGs decoded by `terrainLoader`) or the IGN terrain model (France, raised by the geoid); NASA's on the Moon\n * and Mars; an ArcGIS image service asked for in the body's Mercator. `terrainLoader`: the loader of PNG tiles in an\n * encoding, the same for the same tiles (the engine keeps its tiles when only the exaggeration changes) */\nexport function terrainSettings(\n terrain: boolean | TerrainModel | TerrainOptions | undefined,\n body: CelestialBody | undefined,\n radius: number,\n terrainLoader: (url: string, encoding: PngEncoding, floor?: number) => TerrainLoader,\n): Settings['terrain'] {\n if (!terrain) return undefined;\n let options: TerrainOptions = {};\n if (typeof terrain === 'string') options = { model: terrain };\n else if (terrain !== true) options = terrain;\n const earth = (body ?? 'earth') === 'earth';\n const exaggeration = options.exaggeration ?? 1;\n if (options.url === undefined && earth) {\n if (options.model === 'ign') {\n const geoid = options.geoid ?? true;\n return { url: TERRAIN_URL, exaggeration, maxZoom: options.maxZoom ?? 15, geoid, attribution: IGN_ATTRIBUTION };\n }\n return {\n url: TERRAIN_TILES.url,\n exaggeration,\n maxZoom: options.maxZoom ?? TERRAIN_TILES.maxZoom,\n geoid: options.geoid ?? false,\n // The sea floor of the model at sea level: the oceans stay flat under the basemap's water\n loader: terrainLoader(TERRAIN_TILES.url, 'terrarium', 0),\n attribution: TERRAIN_TILES_ATTRIBUTION,\n };\n }\n const preset = body === 'moon' || body === 'mars' ? BODY_TERRAINS[body] : undefined;\n const url = options.url ?? preset?.url;\n if (url === undefined) throw new Error('isard: the relief of this body needs a url');\n const encoding = options.encoding ?? 'float32';\n // PNG encodings are fetched tile by tile: a {bbox} or an image service would be fetched as it is\n if (\n encoding !== 'float32' &&\n (IMAGE_SERVER.test(url) || !/\\{z\\}/.test(url) || !/\\{x\\}/.test(url) || !/\\{y\\}/.test(url))\n ) {\n throw new Error(`isard: the '${encoding}' terrain encoding takes a tile URL with {z}, {x} and {y} (${url})`);\n }\n return {\n url: IMAGE_SERVER.test(url) ? imageServerTerrain(url, earth, radius) : url,\n exaggeration,\n maxZoom: options.maxZoom ?? (options.url === undefined && preset ? preset.maxZoom : 15),\n geoid: options.geoid ?? false,\n ...(encoding === 'float32' ? {} : { loader: terrainLoader(url, encoding) }),\n // NASA's credits for its models\n ...(options.url === undefined && preset ? { attribution: preset.attribution } : {}),\n };\n}\n\n/** Sky settings for the engine: colors (RGB 0-1) and blends, MapLibre's defaults */\nexport function atmosphereSettings(options: AtmosphereOptions | undefined): Float32Array | undefined {\n if (!options) return undefined;\n return Float32Array.from([\n ...rgb(options.skyColor ?? '#9cc7ec'),\n ...rgb(options.horizonColor ?? '#e8f1f8'),\n ...rgb(options.fogColor ?? '#f2f5f8'),\n options.skyHorizonBlend ?? 0.6,\n options.horizonFogBlend ?? 0.7,\n options.fogGroundBlend ?? 0.4,\n ]);\n}\n\n/** A CSS color to RGB 0-1 (its alpha dropped); black if unknown */\nexport function rgb(color: string): [r: number, g: number, b: number] {\n const [r, g, b] = parseCssColor(color) ?? [0, 0, 0, 1];\n return [r, g, b];\n}\n"]}
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The settings of a map's engine from its options: the body, its halo, its relief, the sky. Kept by the map and\n * replayed on a new engine (after a context loss, or on the engine with 3D Tiles).\n */\nimport {\n BODY_TERRAINS,\n IGN_ATTRIBUTION,\n IMAGE_SERVER,\n imageServerTerrain,\n TERRAIN_TILES,\n TERRAIN_TILES_ATTRIBUTION,\n TERRAIN_URL,\n} from './basemap/basemaps.ts';\nimport type { PngEncoding } from './basemap/terrain.ts';\nimport type {\n AtmosphereOptions,\n BodyOptions,\n CelestialBody,\n LoadingMode,\n TerrainModel,\n TerrainOptions,\n} from './types.ts';\nimport { parseCssColor } from './util/color.ts';\n\n/** Decodes the relief tiles of a URL for the engine: 256 × 256 altitudes, null where there is no tile */\nexport type TerrainLoader = (z: number, x: number, y: number, signal: AbortSignal) => Promise<Float32Array | null>;\n\n/** Settings replayed on a new engine after a WebGL context loss */\nexport interface Settings {\n body: Required<BodyOptions>;\n zoomRange: [min: number, max: number];\n maxPitch: number;\n globe: boolean;\n sky: boolean;\n atmosphere: Float32Array | undefined;\n terrain:\n | {\n url: string;\n exaggeration: number;\n maxZoom: number;\n geoid: boolean;\n /** Decodes the tiles of `url` for the engine (an encoding other than raw floats) */\n loader?: TerrainLoader;\n /** Credits of the model */\n attribution?: string;\n }\n | undefined;\n loading: LoadingMode;\n background: [r: number, g: number, b: number];\n globeColor: [r: number, g: number, b: number];\n}\n\n/** The named bodies; a body's `color` is that of its globe under the tiles (the Earth's follows its basemap), its\n * `relief` the range of its ground (the Earth's dry land, from the Dead Sea to Everest). Mars: the sphere of its\n * equatorial radius (its data take planetocentric latitudes), a faint butterscotch halo of dust */\nconst BODIES: Record<Exclude<CelestialBody, BodyOptions>, Required<BodyOptions>> = {\n earth: { radius: 6378137, flattening: 1 / 298.257223563, atmosphere: true, color: '#cacaca', relief: [-450, 8900] },\n moon: { radius: 1737400, flattening: 0, atmosphere: false, color: '#77756f', relief: [-9200, 10800] },\n mars: {\n radius: 3396190,\n flattening: 0,\n atmosphere: 'rgba(232, 168, 120, 0.6)',\n color: '#b5714a',\n relief: [-8300, 21300],\n },\n};\n\n/** The Earth's halo, RGB 0-1 and its strength: what `atmosphere: true` draws */\nconst EARTH_HALO = Float32Array.of(0.42, 0.66, 1, 1);\n\n/** A body from the option, its defaults filled in */\nexport const bodySettings = (body: CelestialBody | undefined): Required<BodyOptions> => {\n if (body === undefined || typeof body === 'string') return BODIES[body ?? 'earth'];\n\n const relief: [number, number] = [-0.01 * body.radius, 0.01 * body.radius];\n\n return { flattening: 0, atmosphere: false, color: '#808080', relief, ...body };\n};\n\n/** The halo of an atmosphere for the engine (RGB 0-1 and its strength, the color's alpha): undefined for none */\nexport const haloSettings = (atmosphere: boolean | string): Float32Array | undefined => {\n if (atmosphere === true) return EARTH_HALO;\n\n const color = atmosphere === false ? undefined : parseCssColor(atmosphere);\n\n return color && Float32Array.from(color);\n};\n\n/** Relief settings from the option: undefined when off. On the Earth the Terrain Tiles by default (worldwide,\n * Terrarium PNGs decoded by `terrainLoader`) or the IGN terrain model (France, raised by the geoid); NASA's on the Moon\n * and Mars; an ArcGIS image service asked for in the body's Mercator. `terrainLoader`: the loader of PNG tiles in an\n * encoding, the same for the same tiles (the engine keeps its tiles when only the exaggeration changes) */\n/** The relief options of the option on */\nconst terrainOptions = (terrain: true | TerrainModel | TerrainOptions): TerrainOptions => {\n if (typeof terrain === 'string') return { model: terrain };\n\n return terrain === true ? {} : terrain;\n};\n\nexport const terrainSettings = (\n terrain: boolean | TerrainModel | TerrainOptions | undefined,\n body: CelestialBody | undefined,\n radius: number,\n terrainLoader: (url: string, encoding: PngEncoding, floor?: number) => TerrainLoader,\n): Settings['terrain'] => {\n if (!terrain) return undefined;\n\n const options = terrainOptions(terrain);\n const earth = (body ?? 'earth') === 'earth';\n const exaggeration = options.exaggeration ?? 1;\n\n if (options.url === undefined && earth) {\n if (options.model === 'ign') {\n const geoid = options.geoid ?? true;\n\n return { url: TERRAIN_URL, exaggeration, maxZoom: options.maxZoom ?? 15, geoid, attribution: IGN_ATTRIBUTION };\n }\n\n return {\n url: TERRAIN_TILES.url,\n exaggeration,\n maxZoom: options.maxZoom ?? TERRAIN_TILES.maxZoom,\n geoid: options.geoid ?? false,\n // The sea floor of the model at sea level: the oceans stay flat under the basemap's water\n loader: terrainLoader(TERRAIN_TILES.url, 'terrarium', 0),\n attribution: TERRAIN_TILES_ATTRIBUTION,\n };\n }\n\n const preset = body === 'moon' || body === 'mars' ? BODY_TERRAINS[body] : undefined;\n const url = options.url ?? preset?.url;\n\n if (url === undefined) throw new Error('isard: the relief of this body needs a url');\n\n const encoding = options.encoding ?? 'float32';\n\n // PNG encodings are fetched tile by tile: a {bbox} or an image service would be fetched as it is\n if (\n encoding !== 'float32' &&\n (IMAGE_SERVER.test(url) || !/\\{z\\}/.test(url) || !/\\{x\\}/.test(url) || !/\\{y\\}/.test(url))\n ) {\n throw new Error(`isard: the '${encoding}' terrain encoding takes a tile URL with {z}, {x} and {y} (${url})`);\n }\n\n return {\n url: IMAGE_SERVER.test(url) ? imageServerTerrain(url, earth, radius) : url,\n exaggeration,\n maxZoom: options.maxZoom ?? (options.url === undefined && preset ? preset.maxZoom : 15),\n geoid: options.geoid ?? false,\n ...(encoding === 'float32' ? {} : { loader: terrainLoader(url, encoding) }),\n // NASA's credits for its models\n ...(options.url === undefined && preset ? { attribution: preset.attribution } : {}),\n };\n};\n\n/** Sky settings for the engine: colors (RGB 0-1) and blends, MapLibre's defaults */\nexport const atmosphereSettings = (options: AtmosphereOptions | undefined): Float32Array | undefined => {\n if (!options) return undefined;\n\n return Float32Array.from([\n ...rgb(options.skyColor ?? '#9cc7ec'),\n ...rgb(options.horizonColor ?? '#e8f1f8'),\n ...rgb(options.fogColor ?? '#f2f5f8'),\n options.skyHorizonBlend ?? 0.6,\n options.horizonFogBlend ?? 0.7,\n options.fogGroundBlend ?? 0.4,\n ]);\n};\n\n/** A CSS color to RGB 0-1 (its alpha dropped); black if unknown */\nexport const rgb = (color: string): [r: number, g: number, b: number] => {\n const [r, g, b] = parseCssColor(color) ?? [0, 0, 0, 1];\n\n return [r, g, b];\n};\n"]}
package/dist/types.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  /** Public types of the `isard` package */
2
- import type { AttributionOptions } from './controls.ts';
3
- import type { DecoderUrls } from './decoders.ts';
4
- import type { Feature, Ramp, Size } from './features.ts';
5
- import type { TileGrid } from './grid.ts';
6
- import type { Layer } from './layers.ts';
2
+ import type { TileGrid } from './basemap/grid.ts';
3
+ import type { DecoderUrls } from './engine/decoders.ts';
4
+ import type { Feature, Ramp, Size } from './layers/features.ts';
5
+ import type { Layer } from './layers/layers.ts';
6
+ import type { AttributionOptions } from './ui/controls.ts';
7
7
  import type { Camera, Engine } from './wasm/isard.js';
8
8
  export type LonLat = [lon: number, lat: number];
9
9
  export type Point = [x: number, y: number];
@@ -376,11 +376,11 @@ export interface LayerHost {
376
376
  readonly engine: Engine;
377
377
  requestRender(): void;
378
378
  /** Forgets a removed layer */
379
- detach(layer: object): void;
379
+ detach(layer: Layer): void;
380
380
  /** Moves a layer under `before`, or on top */
381
- moveLayer(layer: object, before: object | undefined): void;
381
+ moveLayer(layer: Layer, before: Layer | undefined): void;
382
382
  /** A layer created again in the engine (new id): put at the place of its old id, which is removed */
383
- replaceLayer(layer: object, old: number): void;
383
+ replaceLayer(layer: Layer, old: number): void;
384
384
  /** Resolves once the map is idle (everything in view loaded and drawn) */
385
385
  whenIdle(): Promise<void>;
386
386
  }
package/dist/types.js CHANGED
@@ -1,2 +1,3 @@
1
+ /** Public types of the `isard` package */
1
2
  export {};
2
3
  //# sourceMappingURL=types.js.map
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["/** Public types of the `isard` package */\nimport type { AttributionOptions } from './controls.ts';\nimport type { DecoderUrls } from './decoders.ts';\nimport type { Feature, Ramp, Size } from './features.ts';\nimport type { TileGrid } from './grid.ts';\nimport type { Layer } from './layers.ts';\nimport type { Camera, Engine } from './wasm/isard.js';\n\nexport type LonLat = [lon: number, lat: number];\nexport type Point = [x: number, y: number];\n\n/**\n * The named basemaps. OpenFreeMap's vector styles, OpenStreetMap data worldwide, their labels above the other layers:\n * `osm-positron` (light grey, quiet: data over it reads first), `osm-liberty` and `osm-bright` (in colour). The\n * Géoplateforme's (IGN, France): rasters (`ign-plan`, `ign-plan-grey`, `ign-ortho`, the aerial photographs) or vector\n * tiles with their labels (`ign-plan-vector`, `ign-plan-grey-vector`, the PLAN.IGN styles).\n */\nexport type BasemapName =\n | 'osm-positron'\n | 'osm-liberty'\n | 'osm-bright'\n | 'ign-plan'\n | 'ign-plan-grey'\n | 'ign-ortho'\n | 'ign-plan-vector'\n | 'ign-plan-grey-vector'\n | 'none';\n\n/** A basemap by name (see `BasemapName`) */\nexport type Basemap = BasemapName;\n\n/**\n * The Earth's named terrain models. `'terrain-tiles'`: worldwide, the Terrain Tiles of AWS's open data registry\n * (SRTM, EU-DEM, GMTED… merged by Mapzen, 30 m in most places), the sea floor flattened at sea level. `'ign'`: France,\n * the IGN's RGE ALTI from the Géoplateforme (1 to 5 m), raised by the RAF20 geoid to heights above the ellipsoid.\n */\nexport type TerrainModel = 'terrain-tiles' | 'ign';\n\n/** How tiles encode their altitudes: `'float32'`, raw little-endian floats (`image/x-bil;bits=32`, an ArcGIS raw\n * grid); `'terrarium'`, the colors of a PNG, `R × 256 + G + B / 256 - 32768`; `'mapbox'`, those of Terrain-RGB,\n * `(R × 65536 + G × 256 + B) / 10 - 10000` */\nexport type TerrainEncoding = 'float32' | 'terrarium' | 'mapbox';\n\n/**\n * How tiles load and show. 'immediate' (default): everything visible loads, tiles show as soon as they arrive.\n * 'smooth': during flights the levels flown through are skipped, off-center tiles wait while the camera moves, tiles\n * fade in; fewer downloads, for slow networks or GPUs.\n */\nexport type LoadingMode = 'immediate' | 'smooth';\n\n/** 'globe': a sphere at low zoom, blending into Web Mercator between zooms 5 and 7, up to three levels later under a\n * tilted camera (it sees much farther than its center: the horizon stays curved) */\nexport type Projection = 'globe' | 'mercator';\n\n/** A body to draw the map on, other than the named ones (`CelestialBody`) */\nexport interface BodyOptions {\n /** Equatorial radius, metres */\n radius: number;\n /** Flattening of its ellipsoid, 0 for a sphere (default 0) */\n flattening?: number;\n /** An atmosphere: its halo around the globe, true for the Earth's light blue, or a CSS color (its alpha the\n * halo's strength) (default false) */\n atmosphere?: boolean | string;\n /** Color of the globe where no tile covers it (past the Web Mercator latitudes, 85°), a CSS color (default\n * `#808080`) */\n color?: string;\n /** Lowest and highest altitudes of its ground, metres around the ellipsoid: what its relief may raise into view\n * (default ±1 % of the radius) */\n relief?: [lowest: number, highest: number];\n}\n\n/**\n * The body the map is drawn on: 'earth' (WGS 84, the default), 'moon' (a sphere of 1 737 400 m, no atmosphere),\n * 'mars' (a sphere of 3 396 190 m, its equatorial radius, a thin dusty halo; planetocentric latitudes) or another\n * one. Zoom levels keep their meaning on screen (the Web Mercator tile pyramid), their metres follow the body:\n * altitudes, relief, buildings, 3D Tiles. Off the Earth, the map has none of the Earth's defaults: no basemap, no\n * credits, and space for its background; the Moon and Mars have NASA's relief for `terrain: true`.\n */\nexport type CelestialBody = 'earth' | 'moon' | 'mars' | BodyOptions;\n\nexport interface GeoMapOptions extends Partial<Camera> {\n /** The body the map is drawn on (default 'earth'); set at creation */\n body?: CelestialBody;\n /** Default 'globe' */\n projection?: Projection;\n /** Default 'immediate' */\n loading?: LoadingMode;\n /** The basemap (default 'osm-positron'; 'none' off the Earth) */\n basemap?: Basemap;\n /** Opacity of the IGN hillshade over the basemap (France, Géoplateforme), 0 for none (default 0) */\n hillshade?: number;\n /** Color behind the map (sky of tilted flat views), a CSS color (default `#f2f2f0`; black off the Earth) */\n background?: string;\n /** Space behind the globe: stars and atmosphere halo, fading out as the globe turns flat (default true) */\n sky?: boolean;\n /** Relief under the basemap: true for the body's terrain model (on the Earth the worldwide Terrain Tiles; NASA's on\n * the Moon and Mars: LOLA, MOLA), one of the Earth's models by name (`'ign'`: France, RGE ALTI), or its options\n * (default false; on another body, its `url` is required). Network layers are draped on it */\n terrain?: boolean | TerrainModel | TerrainOptions;\n minZoom?: number;\n maxZoom?: number;\n /** Highest pitch, degrees, up to 85 (default 70) */\n maxPitch?: number;\n /** Sky over the plane, seen when the camera is tilted towards the horizon, and the fog the ground fades into\n * (MapLibre's `setSky`); default none: the background color */\n atmosphere?: AtmosphereOptions;\n /** Mouse, touch and keyboard controls (default true) */\n interactive?: boolean;\n /** Keyboard controls once the map has the focus (it is reached with Tab): arrows pan, Shift + arrows rotate and\n * tilt, + and - zoom (Shift: two levels), 0 faces north and levels the view (default true; none when not\n * `interactive`) */\n keyboard?: boolean;\n /** Accessible name of the map, read by screen readers (default 'Map') */\n ariaLabel?: string;\n /** A preset of map options (`IGN_PRESETS`: `'ign'`, `'ign-3d'`, `'ign-ortho-3d'`), the other options over it */\n preset?: 'ign' | 'ign-3d' | 'ign-ortho-3d';\n /** The folder isard's files are served from (its engines, `isard_bg.wasm`, `isard_core_bg.wasm`,\n * `isard_points_bg.wasm`, and its workers, `decoder.worker.js`, `basemap.worker.js`): one option for a bundler that\n * moves them, the `…Url` options below for each one. `isard/vite` sets it for the whole page; default next to the\n * module */\n assetsUrl?: string | URL;\n /** Where to load the engine with 3D Tiles from (`isard_bg.wasm`), when a bundler does not resolve the default URL.\n * Given without `coreWasmUrl`, maps load this engine from the start */\n wasmUrl?: string | URL;\n /** Where to load the engine without 3D Tiles from (`isard_core_bg.wasm`, a third smaller), when a bundler does not\n * resolve the default URL. Maps load it first, and the engine with 3D Tiles (`wasmUrl`) for their first 3D Tiles\n * layer only */\n coreWasmUrl?: string | URL;\n /** Where the decoding workers load the point cloud module from (`isard_points_bg.wasm`, the LAZ decoder of COPC),\n * when a bundler does not resolve the default URL. Loaded with the first point cloud only */\n pointsWasmUrl?: string | URL;\n /** Load the engine with 3D Tiles from the start (default false: it is loaded when the first 3D Tiles layer or glTF\n * model is added, the map then moving its camera and layers onto it, a stall of about a frame or two). For a map that shows 3D Tiles\n * at once: one engine downloaded instead of two. `'preload'`: the map starts on the engine without 3D Tiles and\n * downloads and compiles the other once idle, without running it: its first 3D Tiles layer does not wait for the\n * download (for a map that will show 3D Tiles later, on demand) */\n tiles3d?: boolean | 'preload';\n /** Where to load the vector basemap worker from, when a bundler does not resolve the default URL */\n basemapWorkerUrl?: string | URL;\n /** Texture size of the vector basemap's tiles, pixels (default 512: lines and edges sharp at every zoom on a screen\n * of pixel ratio 1). 256: a quarter of the drawing in the workers, of the uploads and of the GPU memory, for lines\n * and edges a little softer between two zoom levels (the tiles are shown 181 to 362 CSS pixels wide) */\n basemapTileSize?: number;\n /** Glyphs of the symbol layers: a URL with `{fontstack}` and `{range}` (MapLibre's glyph format; default\n * OpenFreeMap's fonts, Noto Sans). A vector basemap's labels take the glyphs of its style */\n glyphs?: string;\n /** Workers decoding 3D Tiles off the main thread: a count, or false to decode on the main thread (default: cores - 1,\n * 1 to 4). False (or 0) also decodes the PNG relief and reprojects the equirectangular rasters on the main thread,\n * else done by the vector basemap's workers */\n workers?: number | false;\n /** Where to load the decoding worker from, when a bundler does not resolve the default URL */\n workerUrl?: string | URL;\n /** Folders of the Draco and Basis Universal decoders, loaded by the workers on first use (default: the official\n * builds on gstatic.com and jsDelivr; self-host them for offline or locked-down networks). They run through\n * `new Function`: a Content Security Policy needs `'unsafe-eval'` (see `DecoderUrls`) */\n decoders?: Partial<DecoderUrls>;\n /** Credits at the bottom right: false for none, or its options (default true: the credits of the basemap,\n * hillshade and relief in use, compact on maps narrower than 640 px) */\n attributionControl?: boolean | AttributionOptions;\n}\n\nexport interface TerrainOptions {\n /** One of the Earth's named models (default `'terrain-tiles'` on the Earth); unused with a `url` */\n model?: TerrainModel;\n /** Altitudes of 256 × 256 tiles in `encoding`: a WMS GetMap URL with {bbox} (EPSG:3857 on the Earth, the body's\n * Mercator metres elsewhere: the sphere of its radius), a tile URL with {z}, {x} and {y}, or an ArcGIS image service\n * (a URL ending in `/ImageServer`), asked for raw altitudes in the body's Mercator (default: the `model`'s; on the\n * Moon and Mars, NASA's Trek LOLA and MOLA models) */\n url?: string;\n /** How the tiles of `url` encode their altitudes (default `'float32'`); `'terrarium'` and `'mapbox'` take a URL with\n * {z}, {x} and {y} */\n encoding?: TerrainEncoding;\n /** Vertical exaggeration, 1 for the true relief (default 1) */\n exaggeration?: number;\n /** Finest level of the relief, up to 15 (default 15; 14 for the Terrain Tiles, 8 for the Moon's and Mars's models). It\n * starts at level 6 on the Earth, coarser on bodies of a larger relief for their size (3 on the Moon and Mars) */\n maxZoom?: number;\n /** Altitudes over mainland France raised by the height of the RAF20 geoid (the French one, 0 away from France), to\n * heights above the ellipsoid (those of 3D Tiles); false keeps the altitudes as served (NGF-IGN69 for the IGN's)\n * (default true for the `'ign'` model, false otherwise) */\n geoid?: boolean;\n}\n\n/** Sky, horizon and fog over the plane, with the names and meanings of MapLibre's `setSky` */\nexport interface AtmosphereOptions {\n /** A CSS color (default `#9cc7ec`) */\n skyColor?: string;\n /** (default `#e8f1f8`) */\n horizonColor?: string;\n /** (default `#f2f5f8`) */\n fogColor?: string;\n /** Blend from the horizon to the sky color, share of the field of view above the horizon, 0-1 (default 0.6) */\n skyHorizonBlend?: number;\n /** Blend from the horizon to the fog color below the horizon, 0-1 (default 0.7) */\n horizonFogBlend?: number;\n /** Share of the distance to the far plane over which the ground fades into the fog, 0-1 (default 0.4) */\n fogGroundBlend?: number;\n}\n\n/** What can be seen from a point (`GeoMap.setViewshed`); with several observers, the colors, the opacity and the\n * cone's color are the first one's */\nexport interface ViewshedOptions {\n /** The observer */\n position: LonLat;\n /** Metres above the ground (default 1.7, eye level) */\n height?: number;\n /** Metres around the observer that are tinted (default 1000) */\n range?: number;\n /** A CSS color for what is seen (default `#2f9e44`) */\n visibleColor?: string;\n /** A CSS color for what is hidden (default `#e03131`) */\n hiddenColor?: string;\n /** How strongly the colors tint the scene, multiplied into it so that its textures and shading stay, 0-1 (default\n * 0.7) */\n opacity?: number;\n /** A CSS color for the cone drawn in 3D (one way only): its fan through the axis, at the eye's height and tilted\n * with it, from the eye to the range; solid where nothing hides it, faint behind the scene; none by default */\n coneColor?: string;\n /** To look one way only (a camera, a lookout), degrees clockwise from north; all around without it */\n direction?: number;\n /** Degrees above the horizon the cone looks, negative below (default 0) */\n tilt?: number;\n /** Angle of view across, degrees (default 60) */\n fov?: number;\n /** Angle of view up and down, degrees (default 40) */\n verticalFov?: number;\n}\n\n/** An eye at street level (`GeoMap.setFirstPerson`) */\nexport interface FirstPersonView {\n /** Where it stands */\n lonLat: LonLat;\n /** Metres above the ground (default 1.7) */\n height?: number;\n /** Degrees clockwise from north it looks to */\n bearing: number;\n /** Degrees from straight down: 90 level (the default), 180 straight up */\n pitch?: number;\n /** Vertical field of view, degrees (default 75) */\n fov?: number;\n}\n\n/** Layers shown on one side of a vertical line only (`GeoMap.setSwipe`) */\nexport interface SwipeOptions {\n /** CSS pixels from the left of the map */\n position: number;\n layers: readonly Layer[];\n /** The side they show on (default 'left') */\n side?: 'left' | 'right';\n}\n\n/** Animation of a camera move */\nexport interface AnimationOptions {\n /** Milliseconds */\n duration?: number;\n /** Progress over time, both 0 to 1 */\n easing?: (t: number) => number;\n}\n\nexport interface FlyToOptions extends AnimationOptions {\n /** How far the flight zooms out on its way, as MapLibre's `curve` (default 1.42) */\n curve?: number;\n /** Average speed in screens per second when `duration` is not given (default 1.2) */\n speed?: number;\n}\n\n/**\n * Tile grid of a raster's URL. 'mercator': Web Mercator (XYZ, WMTS PM), the engine's own. 'equirectangular':\n * longitudes and latitudes (Plate Carrée, EPSG:4326-like), two 256 px tiles side by side at level 0, rows from the\n * north (NASA's Trek WMTS, WorldCRS84Quad). A `TileGrid`: the tile matrices of a WMTS in any CRS (Lambert-93…), or a\n * WMS asked for each tile's box in its CRS. The last two are reprojected into Web Mercator tiles by the map's workers\n * (in the page with `workers: false`).\n */\nexport type RasterGrid = 'mercator' | 'equirectangular' | TileGrid;\n\n/** What `RasterLayer.setStyle` changes */\nexport interface RasterStyle {\n opacity: number;\n /** 0 = greyscale, 1 = original colors */\n saturation: number;\n}\n\nexport interface RasterOptions {\n /** Tile URL with {z}, {x} and {y} (256 px tiles); unused with a `loader` */\n url: string;\n /** Tile grid of `url` (default 'mercator'); with 'equirectangular', `minZoom` and `maxZoom` are levels of that\n * grid; with a `TileGrid`, they are map zooms, by default those its matrices span */\n grid?: RasterGrid;\n minZoom?: number;\n maxZoom?: number;\n opacity?: number;\n /** 0 = greyscale, 1 = original colors */\n saturation?: number;\n /** Side of the tiles' textures, pixels (default 256): more for sharper tiles drawn by a `loader` */\n size?: number;\n /** Draws each tile instead of fetching `url`: an image of `size` × `size`, null for nothing there; a rejection is\n * retried like a network error */\n loader?: (z: number, x: number, y: number, signal: AbortSignal) => Promise<ImageBitmap | null>;\n /** Credits of the tiles, HTML: shown by the attribution control while the layer is on the map */\n attribution?: string;\n}\n\nexport interface NetworkStyle {\n /** Line width, CSS pixels, or zoom stops `[[zoom, width], …]` (default 2) */\n width: Size;\n /** Values above are drawn as unreached (default 1800) */\n max: number;\n /** Darker line every `contour` value units, 0 for none (default 0) */\n contour: number;\n opacity: number;\n /** Width of the halo drawn under the lines, CSS pixels or zoom stops, 0 for none (default 0): wide and faint, the\n * reached streets add up into a heat map that fills the blocks */\n halo: Size;\n /** Opacity of the halo at the middle of a line, fading quadratically to its sides (default 0.11) */\n haloOpacity: number;\n /** Colors from 0 to `max`: `[[fraction of max, color], …]` (default green to red) */\n ramp: Ramp | undefined;\n /** Color of the parts beyond `max` or unreached (default `rgba(140, 140, 140, 0.25)`) */\n unreachedColor: string;\n /** Share of `max` over which the colors fade out before it, 0 to 1 (default 0) */\n fade: number;\n}\n\nexport interface NetworkOptions extends Partial<NetworkStyle> {\n /** Node coordinates in degrees: lon0, lat0, lon1, lat1… */\n nodes: Float64Array;\n /** Edges as node index pairs: a0, b0, a1, b1… */\n edges: Uint32Array;\n /** Line of each edge, from A to B: the points of edge e are `points[start[e] .. start[e + 1]]` (lon, lat pairs,\n * counted in points); with fewer than two points an edge is straight. Default: all straight. */\n lines?: { start: Uint32Array; points: Float64Array };\n /** Per edge, the cost of travelling it from A to B then from B to A, in value units (Infinity: closed that way;\n * closed both ways: not drawn). A point along an edge then takes the quickest way there, min(value(A) + cost from\n * A, value(B) + cost from B), as a travel time does. Without costs, values are interpolated along the edges. */\n costs?: Float32Array;\n /** Width factor of each edge (default 1): rail lines wider than streets */\n edgeWidths?: Float32Array;\n}\n\nexport interface Tiles3dStyle {\n /** Screen-space error (CSS pixels) above which a tile is refined: 16 by default, lower is finer and heavier */\n maxScreenSpaceError: number;\n opacity: number;\n /** Size of the points of point cloud tiles (`.pnts`, glTF points), CSS pixels: 2 by default */\n pointSize?: number;\n /** A CSS color multiplying the textures of the meshes, the color of the untextured ones (buildings without\n * textures are light grey without it); none by default */\n color?: string;\n}\n\nexport interface Tiles3dOptions extends Partial<Tiles3dStyle> {\n /** URL of a `tileset.json` (3D Tiles 1.0 b3dm and pnts, 1.1 glb meshes and points, external tilesets) */\n url: string;\n /** Its heights are altitudes above the geoid (NGF-IGN69), as the IGN's Bâtiments 3D, rather than above the\n * ellipsoid (3D Tiles as specified): each tile raised by the RAF20 geoid, onto the IGN relief (default false) */\n geoid?: boolean;\n}\n\nexport interface MapPointerEvent {\n point: Point;\n /** Undefined above the horizon */\n lonLat: LonLat | undefined;\n}\n\n/** What 'hoverfeature' found under the pointer */\nexport interface MapHoverFeatureEvent extends MapPointerEvent {\n /** The feature under the pointer (see `GeoMap.pickFeature`), undefined if none */\n hit: FeatureHit | undefined;\n}\n\n/** A picked feature: its layer handle, its index there and, for line, circle, fill, extrusion, point cloud and 3D\n * Tiles layers, the feature itself (a building of 3D Tiles with its properties) */\nexport interface FeatureHit {\n layer: Layer;\n index: number;\n feature: Feature | undefined;\n}\n\nexport interface MapEvents {\n /** The camera started moving (a gesture, an animation or `setCamera`) */\n movestart: Camera;\n /** The camera moved */\n move: Camera;\n /** The camera stopped: no gesture held, no animation running */\n moveend: Camera;\n /** The map changed size (CSS pixels) */\n resize: { width: number; height: number };\n /** The pointer moved over the map (at most once per frame, not while dragging) */\n hover: MapPointerEvent;\n /** What is under the pointer, picked without stalling the GPU: a frame or two after 'hover', only while listened to\n * (radius and layers in `GeoMap.hoverPicking`) */\n hoverfeature: MapHoverFeatureEvent;\n /** Click without drag */\n click: MapPointerEvent;\n /** A frame was drawn; duration of the engine call in milliseconds */\n render: { ms: number };\n /** Everything in view is loaded and drawn, nothing moves: the end of a load, once after each change (as MapLibre's\n * `idle`). Tiles requested by the first frame count, so it never fires before they arrive. */\n idle: Record<string, never>;\n /** The pointer left the canvas (a mouse going out of the map, or onto a control or marker) */\n leave: Record<string, never>;\n}\n\n/** What a layer handle needs from its map */\nexport interface LayerHost {\n readonly engine: Engine;\n requestRender(): void;\n /** Forgets a removed layer */\n detach(layer: object): void;\n /** Moves a layer under `before`, or on top */\n moveLayer(layer: object, before: object | undefined): void;\n /** A layer created again in the engine (new id): put at the place of its old id, which is removed */\n replaceLayer(layer: object, old: number): void;\n /** Resolves once the map is idle (everything in view loaded and drawn) */\n whenIdle(): Promise<void>;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,0CAA0C","sourcesContent":["/** Public types of the `isard` package */\n\nimport type { TileGrid } from './basemap/grid.ts';\nimport type { DecoderUrls } from './engine/decoders.ts';\nimport type { Feature, Ramp, Size } from './layers/features.ts';\nimport type { Layer } from './layers/layers.ts';\nimport type { AttributionOptions } from './ui/controls.ts';\nimport type { Camera, Engine } from './wasm/isard.js';\n\nexport type LonLat = [lon: number, lat: number];\nexport type Point = [x: number, y: number];\n\n/**\n * The named basemaps. OpenFreeMap's vector styles, OpenStreetMap data worldwide, their labels above the other layers:\n * `osm-positron` (light grey, quiet: data over it reads first), `osm-liberty` and `osm-bright` (in colour). The\n * Géoplateforme's (IGN, France): rasters (`ign-plan`, `ign-plan-grey`, `ign-ortho`, the aerial photographs) or vector\n * tiles with their labels (`ign-plan-vector`, `ign-plan-grey-vector`, the PLAN.IGN styles).\n */\nexport type BasemapName =\n | 'osm-positron'\n | 'osm-liberty'\n | 'osm-bright'\n | 'ign-plan'\n | 'ign-plan-grey'\n | 'ign-ortho'\n | 'ign-plan-vector'\n | 'ign-plan-grey-vector'\n | 'none';\n\n/** A basemap by name (see `BasemapName`) */\nexport type Basemap = BasemapName;\n\n/**\n * The Earth's named terrain models. `'terrain-tiles'`: worldwide, the Terrain Tiles of AWS's open data registry\n * (SRTM, EU-DEM, GMTED… merged by Mapzen, 30 m in most places), the sea floor flattened at sea level. `'ign'`: France,\n * the IGN's RGE ALTI from the Géoplateforme (1 to 5 m), raised by the RAF20 geoid to heights above the ellipsoid.\n */\nexport type TerrainModel = 'terrain-tiles' | 'ign';\n\n/** How tiles encode their altitudes: `'float32'`, raw little-endian floats (`image/x-bil;bits=32`, an ArcGIS raw\n * grid); `'terrarium'`, the colors of a PNG, `R × 256 + G + B / 256 - 32768`; `'mapbox'`, those of Terrain-RGB,\n * `(R × 65536 + G × 256 + B) / 10 - 10000` */\nexport type TerrainEncoding = 'float32' | 'terrarium' | 'mapbox';\n\n/**\n * How tiles load and show. 'immediate' (default): everything visible loads, tiles show as soon as they arrive.\n * 'smooth': during flights the levels flown through are skipped, off-center tiles wait while the camera moves, tiles\n * fade in; fewer downloads, for slow networks or GPUs.\n */\nexport type LoadingMode = 'immediate' | 'smooth';\n\n/** 'globe': a sphere at low zoom, blending into Web Mercator between zooms 5 and 7, up to three levels later under a\n * tilted camera (it sees much farther than its center: the horizon stays curved) */\nexport type Projection = 'globe' | 'mercator';\n\n/** A body to draw the map on, other than the named ones (`CelestialBody`) */\nexport interface BodyOptions {\n /** Equatorial radius, metres */\n radius: number;\n /** Flattening of its ellipsoid, 0 for a sphere (default 0) */\n flattening?: number;\n /** An atmosphere: its halo around the globe, true for the Earth's light blue, or a CSS color (its alpha the\n * halo's strength) (default false) */\n atmosphere?: boolean | string;\n /** Color of the globe where no tile covers it (past the Web Mercator latitudes, 85°), a CSS color (default\n * `#808080`) */\n color?: string;\n /** Lowest and highest altitudes of its ground, metres around the ellipsoid: what its relief may raise into view\n * (default ±1 % of the radius) */\n relief?: [lowest: number, highest: number];\n}\n\n/**\n * The body the map is drawn on: 'earth' (WGS 84, the default), 'moon' (a sphere of 1 737 400 m, no atmosphere),\n * 'mars' (a sphere of 3 396 190 m, its equatorial radius, a thin dusty halo; planetocentric latitudes) or another\n * one. Zoom levels keep their meaning on screen (the Web Mercator tile pyramid), their metres follow the body:\n * altitudes, relief, buildings, 3D Tiles. Off the Earth, the map has none of the Earth's defaults: no basemap, no\n * credits, and space for its background; the Moon and Mars have NASA's relief for `terrain: true`.\n */\nexport type CelestialBody = 'earth' | 'moon' | 'mars' | BodyOptions;\n\nexport interface GeoMapOptions extends Partial<Camera> {\n /** The body the map is drawn on (default 'earth'); set at creation */\n body?: CelestialBody;\n /** Default 'globe' */\n projection?: Projection;\n /** Default 'immediate' */\n loading?: LoadingMode;\n /** The basemap (default 'osm-positron'; 'none' off the Earth) */\n basemap?: Basemap;\n /** Opacity of the IGN hillshade over the basemap (France, Géoplateforme), 0 for none (default 0) */\n hillshade?: number;\n /** Color behind the map (sky of tilted flat views), a CSS color (default `#f2f2f0`; black off the Earth) */\n background?: string;\n /** Space behind the globe: stars and atmosphere halo, fading out as the globe turns flat (default true) */\n sky?: boolean;\n /** Relief under the basemap: true for the body's terrain model (on the Earth the worldwide Terrain Tiles; NASA's on\n * the Moon and Mars: LOLA, MOLA), one of the Earth's models by name (`'ign'`: France, RGE ALTI), or its options\n * (default false; on another body, its `url` is required). Network layers are draped on it */\n terrain?: boolean | TerrainModel | TerrainOptions;\n minZoom?: number;\n maxZoom?: number;\n /** Highest pitch, degrees, up to 85 (default 70) */\n maxPitch?: number;\n /** Sky over the plane, seen when the camera is tilted towards the horizon, and the fog the ground fades into\n * (MapLibre's `setSky`); default none: the background color */\n atmosphere?: AtmosphereOptions;\n /** Mouse, touch and keyboard controls (default true) */\n interactive?: boolean;\n /** Keyboard controls once the map has the focus (it is reached with Tab): arrows pan, Shift + arrows rotate and\n * tilt, + and - zoom (Shift: two levels), 0 faces north and levels the view (default true; none when not\n * `interactive`) */\n keyboard?: boolean;\n /** Accessible name of the map, read by screen readers (default 'Map') */\n ariaLabel?: string;\n /** A preset of map options (`IGN_PRESETS`: `'ign'`, `'ign-3d'`, `'ign-ortho-3d'`), the other options over it */\n preset?: 'ign' | 'ign-3d' | 'ign-ortho-3d';\n /** The folder isard's files are served from (its engines, `isard_bg.wasm`, `isard_core_bg.wasm`,\n * `isard_points_bg.wasm`, and its workers, `decoder.worker.js`, `basemap.worker.js`): one option for a bundler that\n * moves them, the `…Url` options below for each one. `isard/vite` sets it for the whole page; default next to the\n * module */\n assetsUrl?: string | URL;\n /** Where to load the engine with 3D Tiles from (`isard_bg.wasm`), when a bundler does not resolve the default URL.\n * Given without `coreWasmUrl`, maps load this engine from the start */\n wasmUrl?: string | URL;\n /** Where to load the engine without 3D Tiles from (`isard_core_bg.wasm`, a third smaller), when a bundler does not\n * resolve the default URL. Maps load it first, and the engine with 3D Tiles (`wasmUrl`) for their first 3D Tiles\n * layer only */\n coreWasmUrl?: string | URL;\n /** Where the decoding workers load the point cloud module from (`isard_points_bg.wasm`, the LAZ decoder of COPC),\n * when a bundler does not resolve the default URL. Loaded with the first point cloud only */\n pointsWasmUrl?: string | URL;\n /** Load the engine with 3D Tiles from the start (default false: it is loaded when the first 3D Tiles layer or glTF\n * model is added, the map then moving its camera and layers onto it, a stall of about a frame or two). For a map that shows 3D Tiles\n * at once: one engine downloaded instead of two. `'preload'`: the map starts on the engine without 3D Tiles and\n * downloads and compiles the other once idle, without running it: its first 3D Tiles layer does not wait for the\n * download (for a map that will show 3D Tiles later, on demand) */\n tiles3d?: boolean | 'preload';\n /** Where to load the vector basemap worker from, when a bundler does not resolve the default URL */\n basemapWorkerUrl?: string | URL;\n /** Texture size of the vector basemap's tiles, pixels (default 512: lines and edges sharp at every zoom on a screen\n * of pixel ratio 1). 256: a quarter of the drawing in the workers, of the uploads and of the GPU memory, for lines\n * and edges a little softer between two zoom levels (the tiles are shown 181 to 362 CSS pixels wide) */\n basemapTileSize?: number;\n /** Glyphs of the symbol layers: a URL with `{fontstack}` and `{range}` (MapLibre's glyph format; default\n * OpenFreeMap's fonts, Noto Sans). A vector basemap's labels take the glyphs of its style */\n glyphs?: string;\n /** Workers decoding 3D Tiles off the main thread: a count, or false to decode on the main thread (default: cores - 1,\n * 1 to 4). False (or 0) also decodes the PNG relief and reprojects the equirectangular rasters on the main thread,\n * else done by the vector basemap's workers */\n workers?: number | false;\n /** Where to load the decoding worker from, when a bundler does not resolve the default URL */\n workerUrl?: string | URL;\n /** Folders of the Draco and Basis Universal decoders, loaded by the workers on first use (default: the official\n * builds on gstatic.com and jsDelivr; self-host them for offline or locked-down networks). They run through\n * `new Function`: a Content Security Policy needs `'unsafe-eval'` (see `DecoderUrls`) */\n decoders?: Partial<DecoderUrls>;\n /** Credits at the bottom right: false for none, or its options (default true: the credits of the basemap,\n * hillshade and relief in use, compact on maps narrower than 640 px) */\n attributionControl?: boolean | AttributionOptions;\n}\n\nexport interface TerrainOptions {\n /** One of the Earth's named models (default `'terrain-tiles'` on the Earth); unused with a `url` */\n model?: TerrainModel;\n /** Altitudes of 256 × 256 tiles in `encoding`: a WMS GetMap URL with {bbox} (EPSG:3857 on the Earth, the body's\n * Mercator metres elsewhere: the sphere of its radius), a tile URL with {z}, {x} and {y}, or an ArcGIS image service\n * (a URL ending in `/ImageServer`), asked for raw altitudes in the body's Mercator (default: the `model`'s; on the\n * Moon and Mars, NASA's Trek LOLA and MOLA models) */\n url?: string;\n /** How the tiles of `url` encode their altitudes (default `'float32'`); `'terrarium'` and `'mapbox'` take a URL with\n * {z}, {x} and {y} */\n encoding?: TerrainEncoding;\n /** Vertical exaggeration, 1 for the true relief (default 1) */\n exaggeration?: number;\n /** Finest level of the relief, up to 15 (default 15; 14 for the Terrain Tiles, 8 for the Moon's and Mars's models). It\n * starts at level 6 on the Earth, coarser on bodies of a larger relief for their size (3 on the Moon and Mars) */\n maxZoom?: number;\n /** Altitudes over mainland France raised by the height of the RAF20 geoid (the French one, 0 away from France), to\n * heights above the ellipsoid (those of 3D Tiles); false keeps the altitudes as served (NGF-IGN69 for the IGN's)\n * (default true for the `'ign'` model, false otherwise) */\n geoid?: boolean;\n}\n\n/** Sky, horizon and fog over the plane, with the names and meanings of MapLibre's `setSky` */\nexport interface AtmosphereOptions {\n /** A CSS color (default `#9cc7ec`) */\n skyColor?: string;\n /** (default `#e8f1f8`) */\n horizonColor?: string;\n /** (default `#f2f5f8`) */\n fogColor?: string;\n /** Blend from the horizon to the sky color, share of the field of view above the horizon, 0-1 (default 0.6) */\n skyHorizonBlend?: number;\n /** Blend from the horizon to the fog color below the horizon, 0-1 (default 0.7) */\n horizonFogBlend?: number;\n /** Share of the distance to the far plane over which the ground fades into the fog, 0-1 (default 0.4) */\n fogGroundBlend?: number;\n}\n\n/** What can be seen from a point (`GeoMap.setViewshed`); with several observers, the colors, the opacity and the\n * cone's color are the first one's */\nexport interface ViewshedOptions {\n /** The observer */\n position: LonLat;\n /** Metres above the ground (default 1.7, eye level) */\n height?: number;\n /** Metres around the observer that are tinted (default 1000) */\n range?: number;\n /** A CSS color for what is seen (default `#2f9e44`) */\n visibleColor?: string;\n /** A CSS color for what is hidden (default `#e03131`) */\n hiddenColor?: string;\n /** How strongly the colors tint the scene, multiplied into it so that its textures and shading stay, 0-1 (default\n * 0.7) */\n opacity?: number;\n /** A CSS color for the cone drawn in 3D (one way only): its fan through the axis, at the eye's height and tilted\n * with it, from the eye to the range; solid where nothing hides it, faint behind the scene; none by default */\n coneColor?: string;\n /** To look one way only (a camera, a lookout), degrees clockwise from north; all around without it */\n direction?: number;\n /** Degrees above the horizon the cone looks, negative below (default 0) */\n tilt?: number;\n /** Angle of view across, degrees (default 60) */\n fov?: number;\n /** Angle of view up and down, degrees (default 40) */\n verticalFov?: number;\n}\n\n/** An eye at street level (`GeoMap.setFirstPerson`) */\nexport interface FirstPersonView {\n /** Where it stands */\n lonLat: LonLat;\n /** Metres above the ground (default 1.7) */\n height?: number;\n /** Degrees clockwise from north it looks to */\n bearing: number;\n /** Degrees from straight down: 90 level (the default), 180 straight up */\n pitch?: number;\n /** Vertical field of view, degrees (default 75) */\n fov?: number;\n}\n\n/** Layers shown on one side of a vertical line only (`GeoMap.setSwipe`) */\nexport interface SwipeOptions {\n /** CSS pixels from the left of the map */\n position: number;\n layers: readonly Layer[];\n /** The side they show on (default 'left') */\n side?: 'left' | 'right';\n}\n\n/** Animation of a camera move */\nexport interface AnimationOptions {\n /** Milliseconds */\n duration?: number;\n /** Progress over time, both 0 to 1 */\n easing?: (t: number) => number;\n}\n\nexport interface FlyToOptions extends AnimationOptions {\n /** How far the flight zooms out on its way, as MapLibre's `curve` (default 1.42) */\n curve?: number;\n /** Average speed in screens per second when `duration` is not given (default 1.2) */\n speed?: number;\n}\n\n/**\n * Tile grid of a raster's URL. 'mercator': Web Mercator (XYZ, WMTS PM), the engine's own. 'equirectangular':\n * longitudes and latitudes (Plate Carrée, EPSG:4326-like), two 256 px tiles side by side at level 0, rows from the\n * north (NASA's Trek WMTS, WorldCRS84Quad). A `TileGrid`: the tile matrices of a WMTS in any CRS (Lambert-93…), or a\n * WMS asked for each tile's box in its CRS. The last two are reprojected into Web Mercator tiles by the map's workers\n * (in the page with `workers: false`).\n */\nexport type RasterGrid = 'mercator' | 'equirectangular' | TileGrid;\n\n/** What `RasterLayer.setStyle` changes */\nexport interface RasterStyle {\n opacity: number;\n /** 0 = greyscale, 1 = original colors */\n saturation: number;\n}\n\nexport interface RasterOptions {\n /** Tile URL with {z}, {x} and {y} (256 px tiles); unused with a `loader` */\n url: string;\n /** Tile grid of `url` (default 'mercator'); with 'equirectangular', `minZoom` and `maxZoom` are levels of that\n * grid; with a `TileGrid`, they are map zooms, by default those its matrices span */\n grid?: RasterGrid;\n minZoom?: number;\n maxZoom?: number;\n opacity?: number;\n /** 0 = greyscale, 1 = original colors */\n saturation?: number;\n /** Side of the tiles' textures, pixels (default 256): more for sharper tiles drawn by a `loader` */\n size?: number;\n /** Draws each tile instead of fetching `url`: an image of `size` × `size`, null for nothing there; a rejection is\n * retried like a network error */\n loader?: (z: number, x: number, y: number, signal: AbortSignal) => Promise<ImageBitmap | null>;\n /** Credits of the tiles, HTML: shown by the attribution control while the layer is on the map */\n attribution?: string;\n}\n\nexport interface NetworkStyle {\n /** Line width, CSS pixels, or zoom stops `[[zoom, width], …]` (default 2) */\n width: Size;\n /** Values above are drawn as unreached (default 1800) */\n max: number;\n /** Darker line every `contour` value units, 0 for none (default 0) */\n contour: number;\n opacity: number;\n /** Width of the halo drawn under the lines, CSS pixels or zoom stops, 0 for none (default 0): wide and faint, the\n * reached streets add up into a heat map that fills the blocks */\n halo: Size;\n /** Opacity of the halo at the middle of a line, fading quadratically to its sides (default 0.11) */\n haloOpacity: number;\n /** Colors from 0 to `max`: `[[fraction of max, color], …]` (default green to red) */\n ramp: Ramp | undefined;\n /** Color of the parts beyond `max` or unreached (default `rgba(140, 140, 140, 0.25)`) */\n unreachedColor: string;\n /** Share of `max` over which the colors fade out before it, 0 to 1 (default 0) */\n fade: number;\n}\n\nexport interface NetworkOptions extends Partial<NetworkStyle> {\n /** Node coordinates in degrees: lon0, lat0, lon1, lat1… */\n nodes: Float64Array;\n /** Edges as node index pairs: a0, b0, a1, b1… */\n edges: Uint32Array;\n /** Line of each edge, from A to B: the points of edge e are `points[start[e] .. start[e + 1]]` (lon, lat pairs,\n * counted in points); with fewer than two points an edge is straight. Default: all straight. */\n lines?: { start: Uint32Array; points: Float64Array };\n /** Per edge, the cost of travelling it from A to B then from B to A, in value units (Infinity: closed that way;\n * closed both ways: not drawn). A point along an edge then takes the quickest way there, min(value(A) + cost from\n * A, value(B) + cost from B), as a travel time does. Without costs, values are interpolated along the edges. */\n costs?: Float32Array;\n /** Width factor of each edge (default 1): rail lines wider than streets */\n edgeWidths?: Float32Array;\n}\n\nexport interface Tiles3dStyle {\n /** Screen-space error (CSS pixels) above which a tile is refined: 16 by default, lower is finer and heavier */\n maxScreenSpaceError: number;\n opacity: number;\n /** Size of the points of point cloud tiles (`.pnts`, glTF points), CSS pixels: 2 by default */\n pointSize?: number;\n /** A CSS color multiplying the textures of the meshes, the color of the untextured ones (buildings without\n * textures are light grey without it); none by default */\n color?: string;\n}\n\nexport interface Tiles3dOptions extends Partial<Tiles3dStyle> {\n /** URL of a `tileset.json` (3D Tiles 1.0 b3dm and pnts, 1.1 glb meshes and points, external tilesets) */\n url: string;\n /** Its heights are altitudes above the geoid (NGF-IGN69), as the IGN's Bâtiments 3D, rather than above the\n * ellipsoid (3D Tiles as specified): each tile raised by the RAF20 geoid, onto the IGN relief (default false) */\n geoid?: boolean;\n}\n\nexport interface MapPointerEvent {\n point: Point;\n /** Undefined above the horizon */\n lonLat: LonLat | undefined;\n}\n\n/** What 'hoverfeature' found under the pointer */\nexport interface MapHoverFeatureEvent extends MapPointerEvent {\n /** The feature under the pointer (see `GeoMap.pickFeature`), undefined if none */\n hit: FeatureHit | undefined;\n}\n\n/** A picked feature: its layer handle, its index there and, for line, circle, fill, extrusion, point cloud and 3D\n * Tiles layers, the feature itself (a building of 3D Tiles with its properties) */\nexport interface FeatureHit {\n layer: Layer;\n index: number;\n feature: Feature | undefined;\n}\n\nexport interface MapEvents {\n /** The camera started moving (a gesture, an animation or `setCamera`) */\n movestart: Camera;\n /** The camera moved */\n move: Camera;\n /** The camera stopped: no gesture held, no animation running */\n moveend: Camera;\n /** The map changed size (CSS pixels) */\n resize: { width: number; height: number };\n /** The pointer moved over the map (at most once per frame, not while dragging) */\n hover: MapPointerEvent;\n /** What is under the pointer, picked without stalling the GPU: a frame or two after 'hover', only while listened to\n * (radius and layers in `GeoMap.hoverPicking`) */\n hoverfeature: MapHoverFeatureEvent;\n /** Click without drag */\n click: MapPointerEvent;\n /** A frame was drawn; duration of the engine call in milliseconds */\n render: { ms: number };\n /** Everything in view is loaded and drawn, nothing moves: the end of a load, once after each change (as MapLibre's\n * `idle`). Tiles requested by the first frame count, so it never fires before they arrive. */\n idle: Record<string, never>;\n /** The pointer left the canvas (a mouse going out of the map, or onto a control or marker) */\n leave: Record<string, never>;\n}\n\n/** What a layer handle needs from its map */\nexport interface LayerHost {\n readonly engine: Engine;\n requestRender(): void;\n /** Forgets a removed layer */\n detach(layer: Layer): void;\n /** Moves a layer under `before`, or on top */\n moveLayer(layer: Layer, before: Layer | undefined): void;\n /** A layer created again in the engine (new id): put at the place of its old id, which is removed */\n replaceLayer(layer: Layer, old: number): void;\n /** Resolves once the map is idle (everything in view loaded and drawn) */\n whenIdle(): Promise<void>;\n}\n"]}
@@ -2,7 +2,7 @@
2
2
  * Controls: elements in a corner of the map. A control is anything with `onAdd` and `onRemove`, as in MapLibre, so
3
3
  * applications write their own; the navigation buttons and the attribution are built in.
4
4
  */
5
- import type { GeoMap } from './map.ts';
5
+ import type { GeoMap } from '../map.ts';
6
6
  export type ControlPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
7
7
  export interface Control {
8
8
  /** Builds the control's element; the map puts it in its corner */
@@ -5,7 +5,7 @@ const MINUS = svg('<path d="M9.5 13.5h10a1 1 0 0 1 0 2h-10a1 1 0 0 1 0-2z"/>');
5
5
  const COMPASS = svg('<path d="M10.5 14 14.5 6.5 18.5 14z" fill="#e3342f"/><path d="M10.5 15 14.5 22.5 18.5 15z" fill="currentColor" opacity="0.5"/>');
6
6
  const INFO = '<svg width="20" height="20" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" ' +
7
7
  'd="M10 3a7 7 0 1 0 0 14 7 7 0 0 0 0-14zm-1 5.5h2V14H9zM10 5.5a1.1 1.1 0 1 1 0 2.2 1.1 1.1 0 0 1 0-2.2z"/></svg>';
8
- function button(className, label, icon, onClick) {
8
+ const button = (className, label, icon, onClick) => {
9
9
  const element = document.createElement('button');
10
10
  element.type = 'button';
11
11
  element.className = className;
@@ -14,7 +14,7 @@ function button(className, label, icon, onClick) {
14
14
  element.innerHTML = icon;
15
15
  element.addEventListener('click', onClick);
16
16
  return element;
17
- }
17
+ };
18
18
  /** Zoom buttons and compass */
19
19
  export class NavigationControl {
20
20
  options;
@@ -33,6 +33,8 @@ export class NavigationControl {
33
33
  const compass = button('isard-ctrl-compass', 'Reset bearing to north', COMPASS, () => map.easeTo({ bearing: 0, pitch: 0 }, 300));
34
34
  const needle = compass.firstElementChild;
35
35
  const turn = () => {
36
+ if (!(needle instanceof SVGElement))
37
+ return;
36
38
  const { bearing, pitch } = map.getCamera();
37
39
  // Seen from above when tilted: the needle lies back with the ground, squashed by cos(pitch)
38
40
  needle.style.transform = this.options.visualizePitch
@@ -67,10 +69,10 @@ export class AttributionControl {
67
69
  const custom = this.options.customAttribution ?? [];
68
70
  const render = () => {
69
71
  inner.innerHTML = [...map.attributions(), ...(typeof custom === 'string' ? [custom] : custom)].join(' | ');
70
- for (const link of inner.querySelectorAll('a')) {
72
+ inner.querySelectorAll('a').forEach((link) => {
71
73
  link.target = '_blank';
72
74
  link.rel = 'noopener noreferrer';
73
- }
75
+ });
74
76
  };
75
77
  render();
76
78
  this.stopListening = map.onAttributionChange(render);