@panoramax/web-viewer 3.2.3-develop-f219e404 → 3.2.3-develop-6257391e

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 (221) hide show
  1. package/.gitlab-ci.yml +3 -0
  2. package/CHANGELOG.md +19 -0
  3. package/CODE_OF_CONDUCT.md +1 -1
  4. package/README.md +1 -1
  5. package/build/editor.html +10 -1
  6. package/build/index.css +2 -2
  7. package/build/index.css.map +1 -1
  8. package/build/index.html +1 -1
  9. package/build/index.js +1682 -5
  10. package/build/index.js.map +1 -1
  11. package/build/map.html +1 -1
  12. package/build/viewer.html +10 -1
  13. package/build/widgets.html +1 -0
  14. package/config/jest/mocks.js +172 -0
  15. package/config/paths.js +1 -0
  16. package/config/webpack.config.js +26 -0
  17. package/docs/03_URL_settings.md +3 -11
  18. package/docs/05_Compatibility.md +59 -76
  19. package/docs/09_Develop.md +30 -11
  20. package/docs/90_Releases.md +2 -2
  21. package/docs/images/class_diagram.drawio +28 -28
  22. package/docs/images/class_diagram.jpg +0 -0
  23. package/docs/index.md +112 -0
  24. package/docs/reference/components/core/Basic.md +153 -0
  25. package/docs/reference/components/core/CoverageMap.md +160 -0
  26. package/docs/reference/components/core/Editor.md +172 -0
  27. package/docs/reference/components/core/Viewer.md +288 -0
  28. package/docs/reference/components/layout/CorneredGrid.md +29 -0
  29. package/docs/reference/components/layout/Mini.md +45 -0
  30. package/docs/reference/components/menus/MapBackground.md +32 -0
  31. package/docs/reference/components/menus/MapFilters.md +15 -0
  32. package/docs/reference/components/menus/MapLayers.md +15 -0
  33. package/docs/reference/components/menus/MapLegend.md +15 -0
  34. package/docs/reference/components/menus/PictureLegend.md +15 -0
  35. package/docs/reference/components/menus/PictureMetadata.md +15 -0
  36. package/docs/reference/components/menus/PlayerOptions.md +15 -0
  37. package/docs/reference/components/menus/QualityScoreDoc.md +15 -0
  38. package/docs/reference/components/menus/ReportForm.md +15 -0
  39. package/docs/reference/components/menus/ShareMenu.md +15 -0
  40. package/docs/reference/components/ui/Button.md +39 -0
  41. package/docs/reference/components/ui/ButtonGroup.md +36 -0
  42. package/docs/reference/components/ui/CopyButton.md +35 -0
  43. package/docs/reference/components/ui/Grade.md +32 -0
  44. package/docs/reference/components/ui/LinkButton.md +44 -0
  45. package/docs/reference/components/ui/Loader.md +54 -0
  46. package/docs/reference/components/ui/Map.md +214 -0
  47. package/docs/reference/components/ui/MapMore.md +233 -0
  48. package/docs/reference/components/ui/Photo.md +369 -0
  49. package/docs/reference/components/ui/Popup.md +56 -0
  50. package/docs/reference/components/ui/QualityScore.md +45 -0
  51. package/docs/reference/components/ui/SearchBar.md +63 -0
  52. package/docs/reference/components/ui/TogglableGroup.md +39 -0
  53. package/docs/reference/components/ui/widgets/GeoSearch.md +32 -0
  54. package/docs/reference/components/ui/widgets/Legend.md +32 -0
  55. package/docs/reference/components/ui/widgets/MapFiltersButton.md +33 -0
  56. package/docs/reference/components/ui/widgets/MapLayersButton.md +15 -0
  57. package/docs/reference/components/ui/widgets/Player.md +32 -0
  58. package/docs/reference/components/ui/widgets/Share.md +15 -0
  59. package/docs/reference/components/ui/widgets/Zoom.md +15 -0
  60. package/docs/reference/utils/API.md +311 -0
  61. package/docs/reference/utils/InitParameters.md +67 -0
  62. package/docs/reference/utils/URLHandler.md +102 -0
  63. package/docs/reference.md +73 -0
  64. package/docs/shortcuts.md +11 -0
  65. package/docs/tutorials/aerial_imagery.md +19 -0
  66. package/docs/tutorials/authentication.md +10 -0
  67. package/docs/tutorials/custom_widgets.md +64 -0
  68. package/docs/tutorials/map_style.md +27 -0
  69. package/docs/tutorials/migrate_v4.md +122 -0
  70. package/docs/tutorials/synced_coverage.md +42 -0
  71. package/mkdocs.yml +60 -5
  72. package/package.json +10 -7
  73. package/public/editor.html +21 -29
  74. package/public/index.html +3 -3
  75. package/public/map.html +19 -18
  76. package/public/viewer.html +18 -24
  77. package/public/widgets.html +265 -0
  78. package/scripts/doc.js +77 -0
  79. package/src/components/core/Basic.css +44 -0
  80. package/src/components/core/Basic.js +258 -0
  81. package/src/components/core/CoverageMap.css +9 -0
  82. package/src/components/core/CoverageMap.js +105 -0
  83. package/src/components/core/Editor.css +23 -0
  84. package/src/components/core/Editor.js +354 -0
  85. package/src/components/core/Viewer.css +109 -0
  86. package/src/components/core/Viewer.js +707 -0
  87. package/src/components/core/index.js +11 -0
  88. package/src/components/index.js +13 -0
  89. package/src/components/layout/CorneredGrid.js +109 -0
  90. package/src/components/layout/Mini.js +117 -0
  91. package/src/components/layout/index.js +7 -0
  92. package/src/components/menus/MapBackground.js +106 -0
  93. package/src/components/menus/MapFilters.js +386 -0
  94. package/src/components/menus/MapLayers.js +143 -0
  95. package/src/components/menus/MapLegend.js +54 -0
  96. package/src/components/menus/PictureLegend.js +103 -0
  97. package/src/components/menus/PictureMetadata.js +188 -0
  98. package/src/components/menus/PlayerOptions.js +96 -0
  99. package/src/components/menus/QualityScoreDoc.js +36 -0
  100. package/src/components/menus/ReportForm.js +133 -0
  101. package/src/components/menus/Share.js +228 -0
  102. package/src/components/menus/index.js +15 -0
  103. package/src/components/styles.js +365 -0
  104. package/src/components/ui/Button.js +75 -0
  105. package/src/components/ui/ButtonGroup.css +49 -0
  106. package/src/components/ui/ButtonGroup.js +68 -0
  107. package/src/components/ui/CopyButton.js +71 -0
  108. package/src/components/ui/Grade.js +54 -0
  109. package/src/components/ui/LinkButton.js +68 -0
  110. package/src/components/ui/Loader.js +188 -0
  111. package/src/components/{Map.css → ui/Map.css} +5 -17
  112. package/src/components/{Map.js → ui/Map.js} +114 -138
  113. package/src/components/ui/MapMore.js +324 -0
  114. package/src/components/{Photo.css → ui/Photo.css} +6 -6
  115. package/src/components/{Photo.js → ui/Photo.js} +279 -90
  116. package/src/components/ui/Popup.js +145 -0
  117. package/src/components/ui/QualityScore.js +152 -0
  118. package/src/components/ui/SearchBar.js +363 -0
  119. package/src/components/ui/TogglableGroup.js +162 -0
  120. package/src/components/ui/index.js +20 -0
  121. package/src/components/ui/widgets/GeoSearch.css +21 -0
  122. package/src/components/ui/widgets/GeoSearch.js +139 -0
  123. package/src/components/ui/widgets/Legend.js +51 -0
  124. package/src/components/ui/widgets/MapFiltersButton.js +104 -0
  125. package/src/components/ui/widgets/MapLayersButton.js +79 -0
  126. package/src/components/ui/widgets/Player.css +7 -0
  127. package/src/components/ui/widgets/Player.js +148 -0
  128. package/src/components/ui/widgets/Share.js +30 -0
  129. package/src/components/ui/widgets/Zoom.js +82 -0
  130. package/src/components/ui/widgets/index.js +12 -0
  131. package/src/img/panoramax.svg +13 -0
  132. package/src/img/switch_big.svg +20 -10
  133. package/src/index.js +6 -9
  134. package/src/translations/da.json +1 -1
  135. package/src/translations/de.json +1 -1
  136. package/src/translations/en.json +5 -3
  137. package/src/translations/eo.json +1 -1
  138. package/src/translations/es.json +1 -1
  139. package/src/translations/fr.json +5 -3
  140. package/src/translations/hu.json +1 -1
  141. package/src/translations/it.json +1 -1
  142. package/src/translations/ja.json +1 -1
  143. package/src/translations/nl.json +1 -1
  144. package/src/translations/pl.json +1 -1
  145. package/src/translations/sv.json +33 -3
  146. package/src/translations/zh_Hant.json +1 -1
  147. package/src/utils/API.js +74 -42
  148. package/src/utils/InitParameters.js +354 -0
  149. package/src/utils/URLHandler.js +364 -0
  150. package/src/utils/geocoder.js +116 -0
  151. package/src/utils/{I18n.js → i18n.js} +3 -1
  152. package/src/utils/index.js +11 -0
  153. package/src/utils/{Map.js → map.js} +216 -80
  154. package/src/utils/picture.js +433 -0
  155. package/src/utils/utils.js +315 -0
  156. package/src/utils/widgets.js +93 -0
  157. package/tests/components/ui/CopyButton.test.js +52 -0
  158. package/tests/components/ui/Loader.test.js +54 -0
  159. package/tests/components/{Map.test.js → ui/Map.test.js} +19 -61
  160. package/tests/components/{Photo.test.js → ui/Photo.test.js} +89 -57
  161. package/tests/components/ui/Popup.test.js +24 -0
  162. package/tests/components/ui/QualityScore.test.js +17 -0
  163. package/tests/components/ui/SearchBar.test.js +107 -0
  164. package/tests/components/ui/__snapshots__/CopyButton.test.js.snap +34 -0
  165. package/tests/components/ui/__snapshots__/Loader.test.js.snap +56 -0
  166. package/tests/components/{__snapshots__ → ui/__snapshots__}/Map.test.js.snap +11 -38
  167. package/tests/components/{__snapshots__ → ui/__snapshots__}/Photo.test.js.snap +57 -4
  168. package/tests/components/ui/__snapshots__/Popup.test.js.snap +29 -0
  169. package/tests/components/ui/__snapshots__/QualityScore.test.js.snap +11 -0
  170. package/tests/components/ui/__snapshots__/SearchBar.test.js.snap +65 -0
  171. package/tests/utils/API.test.js +1 -14
  172. package/tests/utils/InitParameters.test.js +485 -0
  173. package/tests/utils/URLHandler.test.js +350 -0
  174. package/tests/utils/__snapshots__/URLHandler.test.js.snap +21 -0
  175. package/tests/utils/__snapshots__/picture.test.js.snap +315 -0
  176. package/tests/utils/__snapshots__/widgets.test.js.snap +19 -0
  177. package/tests/utils/geocoder.test.js +37 -0
  178. package/tests/utils/{I18n.test.js → i18n.test.js} +1 -1
  179. package/tests/utils/map.test.js +67 -0
  180. package/tests/utils/picture.test.js +745 -0
  181. package/tests/utils/utils.test.js +288 -0
  182. package/tests/utils/widgets.test.js +90 -0
  183. package/docs/01_Start.md +0 -149
  184. package/docs/02_Usage.md +0 -831
  185. package/docs/04_Advanced_examples.md +0 -216
  186. package/src/Editor.css +0 -37
  187. package/src/Editor.js +0 -361
  188. package/src/StandaloneMap.js +0 -114
  189. package/src/Viewer.css +0 -203
  190. package/src/Viewer.js +0 -1246
  191. package/src/components/CoreView.css +0 -70
  192. package/src/components/CoreView.js +0 -175
  193. package/src/components/Loader.css +0 -74
  194. package/src/components/Loader.js +0 -120
  195. package/src/utils/Exif.js +0 -193
  196. package/src/utils/Utils.js +0 -631
  197. package/src/utils/Widgets.js +0 -562
  198. package/src/viewer/URLHash.js +0 -469
  199. package/src/viewer/Widgets.css +0 -880
  200. package/src/viewer/Widgets.js +0 -1470
  201. package/tests/Editor.test.js +0 -126
  202. package/tests/StandaloneMap.test.js +0 -45
  203. package/tests/Viewer.test.js +0 -366
  204. package/tests/__snapshots__/Editor.test.js.snap +0 -298
  205. package/tests/__snapshots__/StandaloneMap.test.js.snap +0 -30
  206. package/tests/__snapshots__/Viewer.test.js.snap +0 -195
  207. package/tests/components/CoreView.test.js +0 -92
  208. package/tests/components/Loader.test.js +0 -38
  209. package/tests/components/__snapshots__/Loader.test.js.snap +0 -15
  210. package/tests/utils/Exif.test.js +0 -124
  211. package/tests/utils/Map.test.js +0 -113
  212. package/tests/utils/Utils.test.js +0 -300
  213. package/tests/utils/Widgets.test.js +0 -107
  214. package/tests/utils/__snapshots__/Exif.test.js.snap +0 -43
  215. package/tests/utils/__snapshots__/Utils.test.js.snap +0 -41
  216. package/tests/utils/__snapshots__/Widgets.test.js.snap +0 -44
  217. package/tests/viewer/URLHash.test.js +0 -559
  218. package/tests/viewer/Widgets.test.js +0 -127
  219. package/tests/viewer/__snapshots__/URLHash.test.js.snap +0 -108
  220. package/tests/viewer/__snapshots__/Widgets.test.js.snap +0 -403
  221. /package/tests/utils/__snapshots__/{Map.test.js.snap → geocoder.test.js.snap} +0 -0
@@ -1,11 +1,10 @@
1
- // DO NOT REMOVE THE "!": bundled builds breaks otherwise !!!
2
- import maplibregl from "!maplibre-gl";
3
1
  import LoaderImg from "../img/marker.svg";
4
- import { COLORS, QUALITYSCORE_RES_FLAT_VALUES, QUALITYSCORE_RES_360_VALUES, QUALITYSCORE_GPS_VALUES, QUALITYSCORE_POND_RES, QUALITYSCORE_POND_GPS } from "./Utils";
5
- import { autoDetectLocale } from "./I18n";
2
+ import { COLORS, QUALITYSCORE_RES_FLAT_VALUES, QUALITYSCORE_RES_360_VALUES, QUALITYSCORE_GPS_VALUES, QUALITYSCORE_POND_RES, QUALITYSCORE_POND_GPS } from "./utils";
3
+ import { autoDetectLocale } from "./i18n";
4
+ import { BASE_PANORAMA_ID } from "./utils";
6
5
 
7
6
  export const DEFAULT_TILES = "https://panoramax.openstreetmap.fr/pmtiles/basic.json";
8
- export const RASTER_LAYER_ID = "gvs-aerial";
7
+ export const RASTER_LAYER_ID = "pnx-aerial";
9
8
 
10
9
  export const TILES_PICTURES_ZOOM = 15;
11
10
  export const TILES_PICTURES_SYMBOL_ZOOM = 18;
@@ -37,7 +36,7 @@ export const VECTOR_STYLES = {
37
36
  "icon-opacity": ["interpolate", ["linear"], ["zoom"], TILES_PICTURES_SYMBOL_ZOOM, 0, TILES_PICTURES_SYMBOL_ZOOM+1, 1],
38
37
  },
39
38
  "layout": {
40
- "icon-image": ["case", ["==", ["get", "type"], "equirectangular"], "gvs-arrow-360", "gvs-arrow-flat"],
39
+ "icon-image": ["case", ["==", ["get", "type"], "equirectangular"], "pnx-arrow-360", "pnx-arrow-flat"],
41
40
  "icon-size": ["interpolate", ["linear"], ["zoom"], TILES_PICTURES_SYMBOL_ZOOM, 0.5, 24, 1],
42
41
  "icon-rotate": ["to-number", ["get", "heading"]],
43
42
  "icon-allow-overlap": true,
@@ -92,7 +91,7 @@ export function getThumbGif(lang) {
92
91
  thumbGif.src = LoaderImg;
93
92
  thumbGif.alt = lang.loading;
94
93
  thumbGif.title = lang.loading;
95
- thumbGif.classList.add("gvs-map-thumb", "gvs-map-thumb-loader");
94
+ thumbGif.classList.add("pnx-map-thumb", "pnx-map-thumb-loader");
96
95
  return thumbGif;
97
96
  }
98
97
 
@@ -106,7 +105,7 @@ export function getThumbGif(lang) {
106
105
  */
107
106
  export function isLabelLayer(l) {
108
107
  return l.type === "symbol"
109
- && l?.layout?.["text-field"]
108
+ && l?.layout?.["text-field"] !== undefined
110
109
  && (l.minzoom === undefined || l.minzoom < 15);
111
110
  }
112
111
 
@@ -123,9 +122,10 @@ export function isLabelLayer(l) {
123
122
  */
124
123
  export function combineStyles(parent, options) {
125
124
  // Get basic vector styles
126
- const style = parent._api.getMapStyle();
125
+ const style = parent.api.getMapStyle();
127
126
 
128
127
  // Complete styles
128
+ style.layers = style.layers || [];
129
129
  style.layers = style.layers.concat(getMissingLayerStyles(style.sources, style.layers));
130
130
  if(!style.metadata) { style.metadata = {}; }
131
131
 
@@ -138,11 +138,11 @@ export function combineStyles(parent, options) {
138
138
 
139
139
  // Aerial imagery background
140
140
  if(options.raster) {
141
- style.sources["gvs-aerial"] = options.raster;
141
+ style.sources["pnx-aerial"] = options.raster;
142
142
  style.layers.push({
143
143
  "id": RASTER_LAYER_ID,
144
144
  "type": "raster",
145
- "source": "gvs-aerial",
145
+ "source": "pnx-aerial",
146
146
  "layout": {
147
147
  "visibility": options.background === "aerial" ? "visible" : "none",
148
148
  }
@@ -150,7 +150,7 @@ export function combineStyles(parent, options) {
150
150
  }
151
151
 
152
152
  // Filter out general tiles if necessary
153
- if(!parent._options?.users?.includes("geovisio")) {
153
+ if(!parent?.users?.includes("geovisio")) {
154
154
  style.layers.forEach(l => {
155
155
  if(l.source === "geovisio") {
156
156
  if(!l.layout) { l.layout = {}; }
@@ -181,7 +181,7 @@ export function combineStyles(parent, options) {
181
181
 
182
182
  // Override labels to use appropriate language
183
183
  if(style.metadata["panoramax:locales"]) {
184
- let prefLang = parent._options.lang || autoDetectLocale(style.metadata["panoramax:locales"], "latin");
184
+ let prefLang = parent.lang || autoDetectLocale(style.metadata["panoramax:locales"], "latin");
185
185
  if(prefLang.includes("-")) { prefLang = prefLang.split("-")[0]; }
186
186
  if(prefLang.includes("_")) { prefLang = prefLang.split("_")[0]; }
187
187
  style.layers.forEach(l => {
@@ -226,11 +226,11 @@ export function combineStyles(parent, options) {
226
226
  * which didn't offer a MapLibre JSON style directly.
227
227
  *
228
228
  * @param {object} sources Pre-existing MapLibre style sources
229
- * @param {object} layers Pre-existing MapLibre style layers
229
+ * @param {object[]} layers Pre-existing MapLibre style layers
230
230
  * @returns List of layers to add
231
231
  * @private
232
232
  */
233
- export function getMissingLayerStyles(sources, layers) {
233
+ export function getMissingLayerStyles(sources = {}, layers = []) {
234
234
  const newLayers = [];
235
235
 
236
236
  // GeoVisio API <= 2.5.0 : add sequences + pictures
@@ -389,81 +389,217 @@ export function switchCoefValue(expr, newCoefVal) {
389
389
  }
390
390
 
391
391
  /**
392
- * Transforms a set of parameters into an URL-ready string
393
- * It also removes null/undefined values
394
- *
395
- * @param {object} params The parameters object
396
- * @return {string} The URL query part
392
+ * Creates links between map and photo elements.
393
+ * This enable interactions like click on map showing picture.
394
+ *
395
+ * @param {CoreView} parent The view containing both Photo and Map elements
397
396
  * @private
398
397
  */
399
- export function geocoderParamsToURLString(params) {
400
- let p = {};
401
- Object.entries(params)
402
- .filter(e => e[1] !== undefined && e[1] !== null)
403
- .forEach(e => p[e[0]] = e[1]);
398
+ export function linkMapAndPhoto(parent) {
399
+ // Switched picture
400
+ const onPicLoad = e => {
401
+ if(!e.detail.picId || e.detail.picId === BASE_PANORAMA_ID) {
402
+ parent.map.displayPictureMarker();
403
+ if(parent?.isMapWide?.()) {
404
+ parent?.mini?.setAttribute("collapsed", "");
405
+ }
406
+ }
407
+ else {
408
+ parent.map.displayPictureMarker(e.detail.lon, e.detail.lat, parent.psv.getXY().x, e.detail.first);
409
+ if(parent?.isMapWide?.()) {
410
+ parent?.mini?.removeAttribute("collapsed");
411
+ }
412
+ }
413
+ };
414
+ parent.psv.addEventListener("picture-loading", onPicLoad);
415
+ parent.psv.addEventListener("picture-loaded", onPicLoad);
416
+
417
+ // Picture view rotated
418
+ parent.psv.addEventListener("view-rotated", () => {
419
+ let x = parent.psv.getPosition().yaw * (180 / Math.PI);
420
+ x += parent.psv.getPictureOriginalHeading();
421
+ parent.map._picMarker.setRotation(x);
422
+ });
404
423
 
405
- return new URLSearchParams(p).toString();
406
- }
424
+ // Picture preview
425
+ parent.psv.addEventListener("picture-preview-started", e => {
426
+ // Show marker corresponding to selection
427
+ parent.map._picMarkerPreview
428
+ .setLngLat(e.detail.coordinates)
429
+ .setRotation(e.detail.direction || 0)
430
+ .addTo(parent.map);
431
+ });
407
432
 
408
- /**
409
- * Nominatim (OSM) geocoder, ready to use for our Map
410
- * @private
411
- */
412
- export function forwardGeocodingNominatim(config) {
413
- // Transform parameters into Nominatim format
414
- const params = {
415
- q: config.query,
416
- countrycodes: config.countries,
417
- limit: config.limit,
418
- viewbox: config.bbox,
419
- };
433
+ parent.psv.addEventListener("picture-preview-stopped", () => {
434
+ parent.map._picMarkerPreview.remove();
435
+ });
420
436
 
421
- return fetch(`https://nominatim.openstreetmap.org/search?${geocoderParamsToURLString(params)}&format=geojson&polygon_geojson=1&addressdetails=1`)
422
- .then(res => res.json())
423
- .then(res => {
424
- const finalRes = { features: [] };
425
- const listedNames = [];
426
- res.features.forEach(f => {
427
- if(!listedNames.includes(f.properties.display_name)) {
428
- finalRes.features.push({
429
- place_type: ["place"],
430
- place_name: f.properties.display_name,
431
- bounds: new maplibregl.LngLatBounds(f.bbox),
432
- });
433
- listedNames.push(f.properties.display_name);
434
- }
435
- });
436
- return finalRes;
437
+ parent.psv.addEventListener("picture-loaded", e => {
438
+ if (parent.isWidthSmall() && parent._picPopup && e.detail.picId == parent._picPopup._picId) {
439
+ parent._picPopup.remove();
440
+ }
441
+ });
442
+
443
+ // Picture click
444
+ parent.map.on("picture-click", e => {
445
+ parent.select(e.seqId, e.picId);
446
+ if(!parent.psv._myVTour.state.currentNode && parent?._setFocus) { parent._setFocus("pic"); }
447
+ });
448
+
449
+ // Sequence click
450
+ parent.map.on("sequence-click", e => {
451
+ parent.api.getPicturesAroundCoordinates(
452
+ e.coordinates.lat,
453
+ e.coordinates.lng,
454
+ 1,
455
+ 1,
456
+ e.seqId
457
+ ).then(results => {
458
+ if(results?.features?.length > 0) {
459
+ parent.select(results.features[0]?.collection, results.features[0].id);
460
+ if(!parent.psv.getPictureMetadata() && parent?._setFocus) { parent._setFocus("pic"); }
461
+ }
462
+ });
463
+ });
464
+
465
+ // Focus changes
466
+ if(parent._setFocus) {
467
+ // PSV double click
468
+ parent.psv.addEventListener("dblclick", () => { if(parent.isMapWide()) { parent._setFocus("pic"); } });
469
+
470
+ // Map double-click: unselect if focused, toggle focus if unfocused
471
+ parent.map.on("dblclick", () => {
472
+ if(!parent.isMapWide()) { parent._setFocus("map"); }
473
+ else { parent.select(); }
437
474
  });
475
+ }
438
476
  }
439
477
 
440
478
  /**
441
- * Base adresse nationale (FR) geocoder, ready to use for our Map
442
- * @param {object} config Configuration sent by MapLibre GL Geocoder, following the geocoderApi format ( https://github.com/maplibre/maplibre-gl-geocoder/blob/main/API.md#setgeocoderapi )
443
- * @returns {object} GeoJSON Feature collection in Carmen GeoJSON format
479
+ * Adds events related to keyboard
444
480
  * @private
445
481
  */
446
- export function forwardGeocodingBAN(config) {
447
- // Transform parameters into BAN format
448
- const params = { q: config.query, limit: config.limit };
449
- if(typeof config.proximity === "string") {
450
- const [lat, lon] = config.proximity.split(",").map(v => parseFloat(v.trim()));
451
- params.lat = lat;
452
- params.lon = lon;
453
- }
482
+ export function initMapKeyboardHandler(parent) {
483
+ parent.map.keyboard.keydown = function(e) {
484
+ if (e.altKey || e.ctrlKey || e.metaKey) return;
485
+
486
+ // Custom keys
487
+ switch(e.key) {
488
+ case "*":
489
+ case "5":
490
+ parent.moveCenter();
491
+ return;
492
+
493
+ case "PageUp":
494
+ case "9":
495
+ parent.psv.goToNextPicture();
496
+ return;
497
+
498
+ case "PageDown":
499
+ case "3":
500
+ parent.psv.goToPrevPicture();
501
+ return;
502
+
503
+ case "Home":
504
+ case "7":
505
+ e.stopPropagation();
506
+ parent._toggleFocus();
507
+ return;
508
+
509
+ case "End":
510
+ case "1":
511
+ parent.mini.toggleAttribute("collapsed");
512
+ return;
513
+
514
+ case " ":
515
+ case "0":
516
+ parent.psv.toggleSequencePlaying();
517
+ return;
518
+ }
454
519
 
455
- const toPlaceName = p => [p.name, p.district, p.city].filter(v => v).join(", ");
456
- const placeTypeToZoom = { "housenumber": 20, "street": 18, "locality": 15, "municipality": 12 };
457
-
458
- return fetch(`https://api-adresse.data.gouv.fr/search/?${geocoderParamsToURLString(params)}`)
459
- .then(res => res.json())
460
- .then(res => {
461
- res.features = res.features.map(f => ({
462
- place_type: ["place"],
463
- place_name: toPlaceName(f.properties),
464
- center: new maplibregl.LngLat(...f.geometry.coordinates),
465
- zoom: placeTypeToZoom[f.properties.type],
466
- }));
467
- return res;
468
- });
520
+ let zoomDir = 0;
521
+ let bearingDir = 0;
522
+ let pitchDir = 0;
523
+ let xDir = 0;
524
+ let yDir = 0;
525
+
526
+ switch (e.keyCode) {
527
+ case 61:
528
+ case 107:
529
+ case 171:
530
+ case 187:
531
+ zoomDir = 1;
532
+ break;
533
+
534
+ case 189:
535
+ case 109:
536
+ case 173:
537
+ zoomDir = -1;
538
+ break;
539
+
540
+ case 37:
541
+ case 100:
542
+ if (e.shiftKey) {
543
+ bearingDir = -1;
544
+ } else {
545
+ e.preventDefault();
546
+ xDir = -1;
547
+ }
548
+ break;
549
+
550
+ case 39:
551
+ case 102:
552
+ if (e.shiftKey) {
553
+ bearingDir = 1;
554
+ } else {
555
+ e.preventDefault();
556
+ xDir = 1;
557
+ }
558
+ break;
559
+
560
+ case 38:
561
+ case 104:
562
+ if (e.shiftKey) {
563
+ pitchDir = 1;
564
+ } else {
565
+ e.preventDefault();
566
+ yDir = -1;
567
+ }
568
+ break;
569
+
570
+ case 40:
571
+ case 98:
572
+ if (e.shiftKey) {
573
+ pitchDir = -1;
574
+ } else {
575
+ e.preventDefault();
576
+ yDir = 1;
577
+ }
578
+ break;
579
+
580
+ default:
581
+ return;
582
+ }
583
+
584
+ if (this._rotationDisabled) {
585
+ bearingDir = 0;
586
+ pitchDir = 0;
587
+ }
588
+
589
+ return {
590
+ cameraAnimation: (map) => {
591
+ const tr = this._tr;
592
+ map.easeTo({
593
+ duration: 300,
594
+ easeId: "keyboardHandler",
595
+ easing: t => t * (2-t),
596
+ zoom: zoomDir ? Math.round(tr.zoom) + zoomDir * (e.shiftKey ? 2 : 1) : tr.zoom,
597
+ bearing: tr.bearing + bearingDir * this._bearingStep,
598
+ pitch: tr.pitch + pitchDir * this._pitchStep,
599
+ offset: [-xDir * this._panStep, -yDir * this._panStep],
600
+ center: tr.center
601
+ }, {originalEvent: e});
602
+ }
603
+ };
604
+ }.bind(parent.map.keyboard);
469
605
  }