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
@@ -1,13 +1,24 @@
1
+ /**
2
+ * Vector basemaps from a MapLibre style (OpenFreeMap's Positron by default): the fills, lines, circles and raster
3
+ * layers drawn tile by tile in workers into the raster pool, so that they lie on the relief like any basemap and
4
+ * composite with the hillshade in one pass; and the labels of the style's symbol layers in a symbol layer of their own,
5
+ * kept above the application's layers (as MapLibre's `beforeId: firstSymbol` does), listed by the workers, shaped in
6
+ * the page once per vector tile, placed by the engine.
7
+ *
8
+ * Any subset of the style can be drawn on its own raster layer (`raster({ layers })`), at its own place in the stack:
9
+ * rivers from the basemap's data over a flood layer, for instance, restyled with `extraLayers`.
10
+ */
11
+ import { headerRules, onHeaderRules, withHeaders } from "../engine/requests.js";
12
+ import { assetUrl } from "../engine-loader.js";
13
+ import { IGN_ATTRIBUTION } from "../geoplateforme.js";
14
+ import { loadSprites, readPixels } from "../layers/icons.js";
15
+ import { mercatorX, mercatorY } from "../util/geo.js";
16
+ import { isRecord } from "../util/guards.js";
17
+ import { Lru } from "../util/lru.js";
1
18
  import { OPENFREEMAP_ATTRIBUTION } from "./basemaps.js";
2
- import { assetUrl } from "./engine-loader.js";
3
- import { mercatorX, mercatorY } from "./geo.js";
4
- import { IGN_ATTRIBUTION } from "./geoplateforme.js";
5
- import { loadSprites, readPixels } from "./icons.js";
6
- import { Lru } from "./lru.js";
7
19
  import { pmtiles, pmtilesUrl } from "./pmtiles.js";
8
- import { headerRules, onHeaderRules, withHeaders } from "./requests.js";
9
20
  import { SOURCE_CACHE } from "./resample.js";
10
- import { labelFont, } from "./vectorstyle.js";
21
+ import { isStyle, labelFont, } from "./vectorstyle.js";
11
22
  /** OpenFreeMap's styles: OpenStreetMap data in the OpenMapTiles schema, worldwide, free and without a key */
12
23
  export const OPENFREEMAP_STYLES = {
13
24
  positron: 'https://tiles.openfreemap.org/styles/positron',
@@ -28,43 +39,75 @@ export const VECTOR_BASEMAPS = {
28
39
  'ign-plan-grey-vector': PLAN_STYLES.grey,
29
40
  };
30
41
  /** The credits of a known style: OpenFreeMap's, PLAN.IGN's */
31
- export function styleAttribution(style) {
42
+ export const styleAttribution = (style) => {
32
43
  if (typeof style !== 'string')
33
44
  return undefined;
34
- if (Object.values(OPENFREEMAP_STYLES).includes(style))
45
+ if (Object.values(OPENFREEMAP_STYLES).some((s) => s === style))
35
46
  return OPENFREEMAP_ATTRIBUTION;
36
- if (Object.values(PLAN_STYLES).includes(style))
47
+ if (Object.values(PLAN_STYLES).some((s) => s === style))
37
48
  return IGN_ATTRIBUTION;
38
49
  return undefined;
39
- }
50
+ };
40
51
  /** Text or icon size of a style (a number, legacy stops, or the stops of a zoom expression made by the worker) as a
41
52
  * size for the symbol layer */
42
- export function size(value, fallback = 16) {
53
+ export const size = (value, fallback = 16) => {
54
+ const stop = (s) => {
55
+ const [z, v] = Array.isArray(s) ? s : [];
56
+ return [Number(z), Number(v)];
57
+ };
43
58
  if (typeof value === 'number')
44
59
  return value;
45
- if (Array.isArray(value) && value.length > 0 && value.every(Array.isArray)) {
46
- return value.map((s) => [Number(s[0]), Number(s[1])]);
47
- }
48
- if (value && typeof value === 'object' && !Array.isArray(value) && Array.isArray(value.stops)) {
49
- return value.stops.map((s) => {
50
- const [z, v] = s;
51
- return [Number(z), Number(v)];
52
- });
53
- }
60
+ if (Array.isArray(value) && value.length > 0 && value.every(Array.isArray))
61
+ return value.map(stop);
62
+ if (isRecord(value) && Array.isArray(value.stops))
63
+ return value.stops.map(stop);
54
64
  return fallback;
55
- }
65
+ };
66
+ /** The anchors of the symbol layer */
67
+ const ANCHORS = new Set([
68
+ 'center',
69
+ 'top',
70
+ 'bottom',
71
+ 'left',
72
+ 'right',
73
+ 'top-left',
74
+ 'top-right',
75
+ 'bottom-left',
76
+ 'bottom-right',
77
+ ]);
78
+ const isAnchor = (value) => value !== undefined && ANCHORS.has(value);
79
+ /** A style's anchor (`text-anchor`, `icon-anchor`) for the symbol layer: `center` if it is none */
80
+ const anchor = (value) => (isAnchor(value) ? value : 'center');
56
81
  /** Fetches a JSON document (a style, a TileJSON) */
57
- async function json(url) {
82
+ const json = async (url) => {
58
83
  const response = await fetch(url, withHeaders(url));
59
84
  if (!response.ok)
60
85
  throw new Error(`${url}: ${response.status}`);
61
- return (await response.json());
62
- }
86
+ return response.json();
87
+ };
88
+ /** A style fetched: a MapLibre style, or an error */
89
+ const fetchStyle = async (url) => {
90
+ const style = await json(url);
91
+ if (!isStyle(style))
92
+ throw new Error(`${url}: not a MapLibre style`);
93
+ return style;
94
+ };
95
+ const isTileJson = (value) => isRecord(value) &&
96
+ Array.isArray(value.tiles) &&
97
+ value.tiles.every((t) => typeof t === 'string') &&
98
+ (value.maxzoom === undefined || typeof value.maxzoom === 'number');
99
+ /** A TileJSON fetched, or an error */
100
+ const fetchTileJson = async (url) => {
101
+ const tilejson = await json(url);
102
+ if (!isTileJson(tilejson))
103
+ throw new Error(`${url}: not a TileJSON`);
104
+ return tilejson;
105
+ };
63
106
  /**
64
107
  * A style source's tiles and deepest level: a `pmtiles://` archive (its `url`, or a `tiles` template) read for its
65
108
  * header, its tiles then named `pmtiles://<absolute archive URL>/{z}/{x}/{y}` for the workers; other sources as they are
66
109
  */
67
- async function resolveSource(source) {
110
+ const resolveSource = async (source) => {
68
111
  const given = source.url ?? source.tiles?.[0] ?? '';
69
112
  const archive = pmtilesUrl(given.replace(/\/\{z\}\/\{x\}\/\{y\}$/, ''));
70
113
  if (!archive)
@@ -74,20 +117,20 @@ async function resolveSource(source) {
74
117
  };
75
118
  const header = await pmtiles(archive).header();
76
119
  return { tiles: [`pmtiles://${archive}/{z}/{x}/{y}`], maxzoom: source.maxzoom ?? header.maxZoom };
77
- }
120
+ };
78
121
  /** Pause before the labels of tiles that failed are asked for again, when no move brings an update (ms) */
79
122
  const RETRY_LABELS_MS = 3000;
80
123
  /** Default size of a basemap worker pool: cores - 1, 1 to 4 */
81
- export function defaultWorkerCount() {
124
+ export const defaultWorkerCount = () => {
82
125
  return Math.min(4, Math.max(1, (typeof navigator !== 'undefined' ? navigator.hardwareConcurrency || 2 : 2) - 1));
83
- }
126
+ };
84
127
  /** Default URL of the basemap worker: in the page's assets folder (`isard/vite`), else next to the module */
85
- export function defaultWorkerUrl(assetsUrl) {
128
+ export const defaultWorkerUrl = (assetsUrl) => {
86
129
  return assetUrl('basemap.worker.js', undefined, assetsUrl);
87
- }
130
+ };
88
131
  /** Fetch priority of a raster tile drawn by the workers: 'high' near the center of the view, at the current zoom or
89
132
  * coarser; 'low' far from it or finer (prefetch); 'auto' between */
90
- export function tilePriority(z, x, y, camera) {
133
+ export const tilePriority = (z, x, y, camera) => {
91
134
  // A raster tile of level z covers the map at zoom z - 1
92
135
  if (z - 1 > camera.zoom + 1)
93
136
  return 'low';
@@ -96,22 +139,22 @@ export function tilePriority(z, x, y, camera) {
96
139
  const cx = mercatorX(lon) * n;
97
140
  const cy = mercatorY(lat) * n;
98
141
  // Across the antimeridian, the short way
99
- let dx = Math.abs(x + 0.5 - cx) % n;
100
- dx = Math.min(dx, n - dx);
142
+ const along = Math.abs(x + 0.5 - cx) % n;
143
+ const dx = Math.min(along, n - along);
101
144
  const d = Math.hypot(dx, y + 0.5 - cy);
102
145
  if (d <= 1.5)
103
146
  return 'high';
104
147
  return d >= 4 ? 'low' : 'auto';
105
- }
148
+ };
106
149
  /** The worker of a vector tile among `count`: always the same one */
107
- export function workerIndex(vz, vx, vy, count) {
150
+ export const workerIndex = (vz, vx, vy, count) => {
108
151
  // Unsigned: every worker gets its share
109
152
  return ((Math.imul(vx, 73856093) ^ Math.imul(vy, 19349663) ^ vz) >>> 0) % Math.max(1, count);
110
- }
153
+ };
111
154
  /** The worker-side key of a renderer: unique across the `VectorTiles` sharing a pool */
112
- export function rendererKey(namespace, n) {
155
+ export const rendererKey = (namespace, n) => {
113
156
  return `${namespace}:r${n}`;
114
- }
157
+ };
115
158
  /**
116
159
  * @internal Workers drawing vector tiles, shared by the `VectorTiles` of a map: each vector tile always goes to the
117
160
  * same worker, which keeps it decoded for every style drawn from it. Requests are tracked one by one, with their
@@ -130,7 +173,7 @@ export class BasemapWorkers {
130
173
  constructor(count, url, create = (u) => new Worker(u, { type: 'module' })) {
131
174
  this.count = count;
132
175
  this.url = url;
133
- this.workers = Array.from({ length: Math.max(1, count) }, () => {
176
+ const start = () => {
134
177
  const worker = create(url);
135
178
  worker.onmessage = ({ data }) => {
136
179
  const p = this.pending.get(data.id);
@@ -152,10 +195,12 @@ export class BasemapWorkers {
152
195
  if (rules.length > 0)
153
196
  worker.postMessage({ type: 'headers', rules });
154
197
  return worker;
155
- });
198
+ };
199
+ this.workers = [start(), ...Array.from({ length: Math.max(1, count) - 1 }, start)];
156
200
  this.unfollow = onHeaderRules((rules) => {
157
- for (const w of this.workers)
201
+ this.workers.forEach((w) => {
158
202
  w.postMessage({ type: 'headers', rules });
203
+ });
159
204
  });
160
205
  }
161
206
  /** A prefix for the renderer keys of one `VectorTiles` */
@@ -169,12 +214,12 @@ export class BasemapWorkers {
169
214
  /** Rejects the requests of a failed worker */
170
215
  fail(worker, message) {
171
216
  const error = new Error(`isard: ${message}. If a bundler moves the worker, give its URL in the \`basemapWorkerUrl\` option (see "With a bundler" in the guide)`);
172
- for (const [id, p] of this.pending) {
217
+ this.pending.forEach((p, id) => {
173
218
  if (p.worker !== worker)
174
- continue;
219
+ return;
175
220
  this.pending.delete(id);
176
221
  p.reject(error);
177
- }
222
+ });
178
223
  }
179
224
  /** The worker of a vector tile */
180
225
  worker(vz, vx, vy) {
@@ -187,8 +232,9 @@ export class BasemapWorkers {
187
232
  // A renderer tells the workers how many they are: they share the decoded tiles' budget
188
233
  const sent = message.type === 'init' ? { ...message, workers: this.workers.length } : message;
189
234
  // A sprite image is copied to each worker (structured clone)
190
- for (const w of this.workers)
235
+ this.workers.forEach((w) => {
191
236
  w.postMessage(sent);
237
+ });
192
238
  }
193
239
  /** Asks a worker for a tile's image or labels, on behalf of `owner` */
194
240
  request(worker, work, owner, signal) {
@@ -237,13 +283,13 @@ export class BasemapWorkers {
237
283
  }
238
284
  /** Cancels the requests of an owner (the workers stop them) */
239
285
  cancel(owner) {
240
- for (const [id, p] of this.pending) {
286
+ this.pending.forEach((p, id) => {
241
287
  if (p.owner !== owner)
242
- continue;
288
+ return;
243
289
  this.pending.delete(id);
244
290
  p.worker.postMessage({ type: 'abort', id });
245
291
  p.reject(new DOMException('isard: vector tiles destroyed', 'AbortError'));
246
- }
292
+ });
247
293
  }
248
294
  /** Stops the workers; their requests fail */
249
295
  terminate() {
@@ -251,18 +297,20 @@ export class BasemapWorkers {
251
297
  return;
252
298
  this.terminated = true;
253
299
  this.unfollow();
254
- for (const w of this.workers)
300
+ this.workers.forEach((w) => {
255
301
  w.terminate();
302
+ });
256
303
  const pending = [...this.pending.values()];
257
304
  this.pending.clear();
258
- for (const p of pending)
305
+ pending.forEach((p) => {
259
306
  p.reject(new DOMException('isard: vector tiles destroyed', 'AbortError'));
307
+ });
260
308
  }
261
309
  }
262
310
  /** A tile's label candidates as features, by style layer */
263
- export function tileLabels(candidates) {
311
+ export const tileLabels = (candidates) => {
264
312
  const byLayer = new Map();
265
- for (const p of candidates) {
313
+ candidates.forEach((p) => {
266
314
  const feature = {
267
315
  type: 'Feature',
268
316
  properties: p,
@@ -281,9 +329,9 @@ export function tileLabels(candidates) {
281
329
  list.push(feature);
282
330
  else
283
331
  byLayer.set(p.layer, [feature]);
284
- }
332
+ });
285
333
  return [...byLayer].sort((a, b) => b[0] - a[0]);
286
- }
334
+ };
287
335
  export class VectorTiles {
288
336
  map;
289
337
  pool;
@@ -324,16 +372,14 @@ export class VectorTiles {
324
372
  });
325
373
  }
326
374
  async load(input) {
327
- const style = typeof input === 'string' ? await json(input) : input;
375
+ const style = typeof input === 'string' ? await fetchStyle(input) : input;
328
376
  const [name, source] = Object.entries(style.sources).find(([, s]) => s.type === 'vector') ?? [];
329
377
  if (!name || !source)
330
378
  throw new Error('the style has no vector source');
331
- let { tiles, maxzoom } = await resolveSource(source);
332
- if (!tiles && source.url) {
333
- const tilejson = await json(source.url);
334
- tiles = tilejson.tiles;
335
- maxzoom ??= tilejson.maxzoom;
336
- }
379
+ const resolved = await resolveSource(source);
380
+ const tilejson = !resolved.tiles && source.url ? await fetchTileJson(source.url) : undefined;
381
+ const tiles = tilejson === undefined ? resolved.tiles : tilejson.tiles;
382
+ const maxzoom = resolved.maxzoom ?? tilejson?.maxzoom;
337
383
  const template = tiles?.[0];
338
384
  if (!template)
339
385
  throw new Error(`source ${name} has no tiles`);
@@ -357,11 +403,11 @@ export class VectorTiles {
357
403
  /** The fonts of the style's labels, for its glyphs (the first of each `text-font`, as the workers take it) */
358
404
  static fonts(style) {
359
405
  const fonts = new Set();
360
- for (const layer of style.layers) {
406
+ style.layers.forEach((layer) => {
361
407
  const font = layer.layout?.['text-font'];
362
408
  if (layer.type === 'symbol' && Array.isArray(font) && typeof font[0] === 'string')
363
409
  fonts.add(labelFont(font[0]));
364
- }
410
+ });
365
411
  return [...fonts];
366
412
  }
367
413
  /** The style's sprites (their JSON and their images), loaded once, for the fill patterns and the icons */
@@ -443,7 +489,7 @@ export class VectorTiles {
443
489
  color: (p) => p.color,
444
490
  haloColor: (p) => p.haloColor,
445
491
  haloWidth: (p) => p.haloWidth,
446
- anchor: (p) => p.anchor,
492
+ anchor: (p) => anchor(p.anchor),
447
493
  offset: (p) => p.offset,
448
494
  maxWidth: (p) => p.maxWidth,
449
495
  lineHeight: (p) => p.lineHeight,
@@ -452,7 +498,7 @@ export class VectorTiles {
452
498
  textOptional: (p) => p.textOptional === true,
453
499
  icon: (p) => (p.icon ? this.iconPrefix + p.icon.image : ''),
454
500
  iconSize: (p) => size(p.icon?.size ?? 1, 1),
455
- iconAnchor: (p) => (p.icon?.anchor ?? 'center'),
501
+ iconAnchor: (p) => anchor(p.icon?.anchor),
456
502
  iconOffset: (p) => p.icon?.offset ?? [0, 0],
457
503
  iconRotate: (p) => p.icon?.rotate ?? 0,
458
504
  iconRotationAlignment: (p) => p.icon?.alignment ?? 'viewport',
@@ -472,10 +518,10 @@ export class VectorTiles {
472
518
  // Its icons from its sprites, before the first labels
473
519
  const icons = style.layers.some((l) => l.type === 'symbol' && l.layout?.['icon-image'] !== undefined);
474
520
  if (icons && style.sprite) {
475
- for (const sprite of await this.loadSprites(style.sprite)) {
521
+ (await this.loadSprites(style.sprite)).forEach((sprite) => {
476
522
  if (!this.destroyed)
477
523
  this.map.icons.addSprite(this.iconPrefix, sprite.icons, () => readPixels(sprite.image));
478
- }
524
+ });
479
525
  }
480
526
  return this.renderer((l) => l.type === 'symbol' && layers(l), []);
481
527
  });
@@ -500,18 +546,22 @@ export class VectorTiles {
500
546
  if (ground.length > 0) {
501
547
  // The ground's tiles, the nearest first: a tile so many levels coarser than the finest in view has its
502
548
  // labels of a zoom as many under the view's, past the source's deepest level those of that level at the zoom
503
- let top = 0;
504
- for (let i = 0; i < ground.length; i += 3)
505
- top = Math.max(top, ground[i]);
506
- for (let i = 0; i < ground.length && keys.length < maxTiles; i += 3) {
507
- const [z, x, y] = [ground[i], ground[i + 1], ground[i + 2]];
549
+ const groundTiles = Array.from({ length: Math.ceil(ground.length / 3) }, (_, k) => [
550
+ ground[3 * k] ?? 0,
551
+ ground[3 * k + 1] ?? 0,
552
+ ground[3 * k + 2] ?? 0,
553
+ ]);
554
+ const top = groundTiles.reduce((t, [z]) => Math.max(t, z), 0);
555
+ groundTiles.forEach(([z, x, y]) => {
556
+ if (keys.length >= maxTiles)
557
+ return;
508
558
  const at = Math.max(0, zoom - (top - z));
509
559
  const tz = Math.min(at, maxzoom, z);
510
560
  const shift = 2 ** (z - tz);
511
561
  const key = `${tz}/${Math.floor(x / shift)}/${Math.floor(y / shift)}${at > tz ? `@${at}` : ''}`;
512
562
  if (!keys.includes(key))
513
563
  keys.push(key);
514
- }
564
+ });
515
565
  }
516
566
  else {
517
567
  const z = Math.min(zoom, maxzoom);
@@ -531,26 +581,22 @@ export class VectorTiles {
531
581
  Math.max(0, ty(north), Math.floor(cy) - reach),
532
582
  Math.min(n - 1, ty(south), Math.floor(cy) + reach),
533
583
  ];
534
- const wanted = [];
535
- for (let y = y0; y <= y1; y += 1)
536
- for (let x = x0; x <= x1; x += 1)
537
- wanted.push([x, y]);
584
+ const wanted = Array.from({ length: y1 - y0 + 1 }, (_, j) => y0 + j).flatMap((y) => Array.from({ length: x1 - x0 + 1 }, (_, i) => [x0 + i, y]));
538
585
  // Nearest to the center first, at most `maxTiles` (tilted views reach far)
539
586
  wanted.sort((a, b) => Math.hypot(a[0] + 0.5 - cx, a[1] + 0.5 - cy) - Math.hypot(b[0] + 0.5 - cx, b[1] + 0.5 - cy));
540
587
  // Past the source's deepest level, its tiles' labels at the zoom of the view (the layers of the deeper zooms)
541
- for (const [x, y] of wanted.slice(0, maxTiles))
542
- keys.push(`${z}/${x}/${y}${zoom > z ? `@${zoom}` : ''}`);
588
+ keys.push(...wanted.slice(0, maxTiles).map(([x, y]) => `${z}/${x}/${y}${zoom > z ? `@${zoom}` : ''}`));
543
589
  }
544
590
  // The same tiles as the labels shown: nothing to do
545
591
  const set = keys.join(' ');
546
592
  if (set === shown)
547
593
  return;
548
594
  const lists = await Promise.all(keys.map((k, index) => {
549
- let p = tiles.get(k);
550
- if (p)
551
- return p;
595
+ const cached = tiles.get(k);
596
+ if (cached)
597
+ return cached;
552
598
  const [tile, deeper] = k.split('@');
553
- const [tz, x, y] = (tile ?? '').split('/').map(Number);
599
+ const [tz = 0, x = 0, y = 0] = (tile ?? '').split('/').map(Number);
554
600
  // The nearest tiles first: the others wait for the raster tiles
555
601
  const priority = index < 4 ? 'auto' : 'low';
556
602
  const work = {
@@ -562,7 +608,7 @@ export class VectorTiles {
562
608
  priority,
563
609
  ...(deeper === undefined ? {} : { zoom: Number(deeper) }),
564
610
  };
565
- p = this.request(tz, x, y, work).then((r) => tileLabels('labels' in r ? r.labels : []), () => {
611
+ const p = this.request(tz, x, y, work).then((r) => tileLabels('labels' in r ? r.labels : []), () => {
566
612
  // A network error is not kept: the tile is asked for again on the next update
567
613
  tiles.delete(k);
568
614
  return [];
@@ -584,14 +630,7 @@ export class VectorTiles {
584
630
  // The labels of the higher style layers first: they win the collisions; for each style layer, the tiles nearest
585
631
  // to the center first
586
632
  const layerIds = [...new Set(lists.flatMap((list) => list.map(([layer]) => layer)))].sort((a, b) => b - a);
587
- const groups = [];
588
- for (const layer of layerIds) {
589
- for (const list of lists) {
590
- const group = list.find(([l]) => l === layer)?.[1];
591
- if (group)
592
- groups.push(group);
593
- }
594
- }
633
+ const groups = layerIds.flatMap((layer) => lists.map((list) => list.find(([l]) => l === layer)?.[1]).filter((group) => group !== undefined));
595
634
  symbol.setGroups(groups);
596
635
  };
597
636
  // The style failed to load: reported by `ready`
@@ -619,19 +658,22 @@ export class VectorTiles {
619
658
  if (this.destroyed)
620
659
  return;
621
660
  this.destroyed = true;
622
- for (const off of this.cleanup)
661
+ this.cleanup.forEach((off) => {
623
662
  off();
663
+ });
624
664
  this.cleanup.length = 0;
625
- for (const layer of this.layers)
665
+ this.layers.forEach((layer) => {
626
666
  if (this.map.hasLayer(layer))
627
667
  layer.remove();
668
+ });
628
669
  this.layers.length = 0;
629
670
  this.map.dropVectorTiles(this);
630
671
  // The page's copy of the sprites (the workers have theirs), and their icons
631
672
  this.sprites
632
673
  ?.then((sprites) => {
633
- for (const sprite of sprites)
674
+ sprites.forEach((sprite) => {
634
675
  sprite.image.close();
676
+ });
635
677
  this.map.icons.remove(this.iconPrefix, true);
636
678
  })
637
679
  .catch(() => undefined);
@@ -641,8 +683,9 @@ export class VectorTiles {
641
683
  else {
642
684
  // Shared workers: only its requests stop and its renderers go
643
685
  this.pool.cancel(this);
644
- for (const key of this.renderers)
686
+ this.renderers.forEach((key) => {
645
687
  this.pool.broadcast({ type: 'drop', key });
688
+ });
646
689
  }
647
690
  this.renderers.length = 0;
648
691
  }
@@ -655,10 +698,10 @@ const BASIC_COLORS = ['#2f6fd1', '#d1495b', '#2a9d8f', '#e9a03b', '#7b5ea7', '#5
655
698
  * layer, the `name` of points as labels. `source` is the style's vector source (`url`: TileJSON or `pmtiles://…`, or
656
699
  * `tiles`)
657
700
  */
658
- export function basicStyle(source, layers) {
701
+ export const basicStyle = (source, layers) => {
659
702
  const out = [];
660
703
  layers.forEach((name, i) => {
661
- const color = BASIC_COLORS[i % BASIC_COLORS.length];
704
+ const color = BASIC_COLORS[i % BASIC_COLORS.length] ?? '#2f6fd1';
662
705
  const base = { source: 'data', 'source-layer': name };
663
706
  out.push({ id: `${name}-fill`, type: 'fill', ...base, paint: { 'fill-color': color, 'fill-opacity': 0.18 } }, { id: `${name}-line`, type: 'line', ...base, paint: { 'line-color': color, 'line-width': 1.2 } }, {
664
707
  id: `${name}-circle`,
@@ -679,21 +722,24 @@ export function basicStyle(source, layers) {
679
722
  });
680
723
  });
681
724
  return { version: 8, sources: { data: { type: 'vector', ...source } }, layers: out };
682
- }
725
+ };
683
726
  /** HTML of a file reduced to its text, escaped: credits from an archive's metadata cannot run in the page */
684
- function plainText(html) {
727
+ const plainText = (html) => {
685
728
  return html
686
729
  .replace(/<[^>]*>/g, '')
687
730
  .replace(/&(?!(amp|lt|gt|quot|copy|#\d+);)/g, '&amp;')
688
731
  .replace(/</g, '&lt;')
689
732
  .replace(/>/g, '&gt;');
690
- }
733
+ };
691
734
  /** @internal `GeoMap.addPmtiles`: a raster layer of the archive's images, or vector tiles with their raster layer and
692
735
  * labels */
693
- export async function pmtilesLayer(map, url, options) {
694
- const archiveUrl = pmtilesUrl(url.startsWith('pmtiles://') ? url : `pmtiles://${url}`);
736
+ export const pmtilesLayer = async (map, url, options) => {
737
+ const archiveUrl = pmtilesUrl(url.startsWith('pmtiles://') ? url : `pmtiles://${url}`) ?? url;
695
738
  const archive = pmtiles(archiveUrl);
696
- const [header, metadata] = await Promise.all([archive.header(), archive.metadata().catch(() => ({}))]);
739
+ const [header, metadata] = await Promise.all([
740
+ archive.header(),
741
+ archive.metadata().catch(() => ({})),
742
+ ]);
697
743
  const credit = metadata.attribution;
698
744
  const attribution = options.attribution ?? (typeof credit === 'string' && credit ? plainText(credit) : undefined);
699
745
  const kind = options.kind ?? (header.tileType === 'mvt' ? 'vector' : 'raster');
@@ -710,7 +756,9 @@ export async function pmtilesLayer(map, url, options) {
710
756
  });
711
757
  }
712
758
  const layers = metadata.vector_layers;
713
- const names = Array.isArray(layers) ? layers.map((l) => l?.id).filter((id) => typeof id === 'string') : [];
759
+ const names = Array.isArray(layers)
760
+ ? layers.map((l) => (isRecord(l) ? l.id : undefined)).filter((id) => typeof id === 'string')
761
+ : [];
714
762
  const style = options.style ?? basicStyle({ url: `pmtiles://${archiveUrl}` }, names);
715
763
  const tiles = map.vectorTiles({ style, ...credits });
716
764
  tiles.raster({
@@ -719,10 +767,10 @@ export async function pmtilesLayer(map, url, options) {
719
767
  });
720
768
  tiles.labels();
721
769
  return tiles;
722
- }
770
+ };
723
771
  /** A raster loader reading the tiles of a `pmtiles://` archive URL (images of any size, drawn at `size`); undefined
724
772
  * for another URL */
725
- export function pmtilesRasterLoader(url, size) {
773
+ export const pmtilesRasterLoader = (url, size) => {
726
774
  const archiveUrl = pmtilesUrl(url);
727
775
  if (!archiveUrl)
728
776
  return undefined;
@@ -733,5 +781,5 @@ export function pmtilesRasterLoader(url, size) {
733
781
  return null;
734
782
  return createImageBitmap(new Blob([bytes]), { resizeWidth: size, resizeHeight: size });
735
783
  };
736
- }
784
+ };
737
785
  //# sourceMappingURL=vectortiles.js.map