@defra/forms-engine-plugin 4.2.0 → 4.4.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 (98) hide show
  1. package/.public/javascripts/application.min.js.map +1 -1
  2. package/.public/javascripts/shared.min.js +1 -1
  3. package/.public/javascripts/shared.min.js.map +1 -1
  4. package/.public/javascripts/vendor/accessible-autocomplete.min.js.map +1 -1
  5. package/.public/stylesheets/application.min.css +1 -1
  6. package/.public/stylesheets/application.min.css.map +1 -1
  7. package/.server/client/javascripts/geospatial-map.d.ts +189 -0
  8. package/.server/client/javascripts/geospatial-map.js +1068 -0
  9. package/.server/client/javascripts/geospatial-map.js.map +1 -0
  10. package/.server/client/javascripts/location-map.d.ts +6 -91
  11. package/.server/client/javascripts/location-map.js +78 -385
  12. package/.server/client/javascripts/location-map.js.map +1 -1
  13. package/.server/client/javascripts/map.d.ts +199 -0
  14. package/.server/client/javascripts/map.js +384 -0
  15. package/.server/client/javascripts/map.js.map +1 -0
  16. package/.server/client/javascripts/shared.d.ts +3 -1
  17. package/.server/client/javascripts/shared.js +3 -1
  18. package/.server/client/javascripts/shared.js.map +1 -1
  19. package/.server/client/stylesheets/shared.scss +7 -0
  20. package/.server/server/plugins/engine/components/ComponentBase.d.ts +1 -0
  21. package/.server/server/plugins/engine/components/ComponentBase.js +2 -0
  22. package/.server/server/plugins/engine/components/ComponentBase.js.map +1 -1
  23. package/.server/server/plugins/engine/components/FormComponent.d.ts +9 -1
  24. package/.server/server/plugins/engine/components/FormComponent.js +22 -0
  25. package/.server/server/plugins/engine/components/FormComponent.js.map +1 -1
  26. package/.server/server/plugins/engine/components/GeospatialField.d.ts +77 -0
  27. package/.server/server/plugins/engine/components/GeospatialField.js +102 -0
  28. package/.server/server/plugins/engine/components/GeospatialField.js.map +1 -0
  29. package/.server/server/plugins/engine/components/helpers/__stubs__/geospatial.d.ts +3 -0
  30. package/.server/server/plugins/engine/components/helpers/__stubs__/geospatial.js +63 -0
  31. package/.server/server/plugins/engine/components/helpers/__stubs__/geospatial.js.map +1 -0
  32. package/.server/server/plugins/engine/components/helpers/components.d.ts +1 -1
  33. package/.server/server/plugins/engine/components/helpers/components.js +7 -0
  34. package/.server/server/plugins/engine/components/helpers/components.js.map +1 -1
  35. package/.server/server/plugins/engine/components/helpers/geospatial.d.ts +6 -0
  36. package/.server/server/plugins/engine/components/helpers/geospatial.js +71 -0
  37. package/.server/server/plugins/engine/components/helpers/geospatial.js.map +1 -0
  38. package/.server/server/plugins/engine/components/helpers/geospatial.test.js +42 -0
  39. package/.server/server/plugins/engine/components/helpers/geospatial.test.js.map +1 -0
  40. package/.server/server/plugins/engine/components/index.d.ts +1 -0
  41. package/.server/server/plugins/engine/components/index.js +1 -0
  42. package/.server/server/plugins/engine/components/index.js.map +1 -1
  43. package/.server/server/plugins/engine/models/FormModel.js +0 -4
  44. package/.server/server/plugins/engine/models/FormModel.js.map +1 -1
  45. package/.server/server/plugins/engine/pageControllers/PageController.d.ts +1 -0
  46. package/.server/server/plugins/engine/pageControllers/PageController.js +2 -0
  47. package/.server/server/plugins/engine/pageControllers/PageController.js.map +1 -1
  48. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js +2 -4
  49. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js.map +1 -1
  50. package/.server/server/plugins/engine/pageControllers/helpers/state.d.ts +8 -7
  51. package/.server/server/plugins/engine/pageControllers/helpers/state.js +39 -12
  52. package/.server/server/plugins/engine/pageControllers/helpers/state.js.map +1 -1
  53. package/.server/server/plugins/engine/pageControllers/helpers/submission.js +13 -1
  54. package/.server/server/plugins/engine/pageControllers/helpers/submission.js.map +1 -1
  55. package/.server/server/plugins/engine/pageControllers/validationOptions.js +2 -1
  56. package/.server/server/plugins/engine/pageControllers/validationOptions.js.map +1 -1
  57. package/.server/server/plugins/engine/routes/index.js +8 -1
  58. package/.server/server/plugins/engine/routes/index.js.map +1 -1
  59. package/.server/server/plugins/engine/types.d.ts +63 -2
  60. package/.server/server/plugins/engine/types.js +33 -0
  61. package/.server/server/plugins/engine/types.js.map +1 -1
  62. package/.server/server/plugins/engine/views/components/geospatialfield.html +7 -0
  63. package/.server/server/plugins/nunjucks/context.test.js.map +1 -1
  64. package/.server/server/plugins/nunjucks/filters/field.d.ts +1 -1
  65. package/.server/server/routes/types.js.map +1 -1
  66. package/.server/server/services/cacheService.js +3 -0
  67. package/.server/server/services/cacheService.js.map +1 -1
  68. package/package.json +9 -5
  69. package/src/client/javascripts/geospatial-map.js +1023 -0
  70. package/src/client/javascripts/location-map.js +94 -390
  71. package/src/client/javascripts/map.js +389 -0
  72. package/src/client/javascripts/shared.js +3 -1
  73. package/src/client/stylesheets/shared.scss +7 -0
  74. package/src/server/plugins/engine/components/ComponentBase.ts +2 -0
  75. package/src/server/plugins/engine/components/FormComponent.ts +29 -0
  76. package/src/server/plugins/engine/components/GeospatialField.test.ts +380 -0
  77. package/src/server/plugins/engine/components/GeospatialField.ts +145 -0
  78. package/src/server/plugins/engine/components/helpers/__stubs__/geospatial.ts +85 -0
  79. package/src/server/plugins/engine/components/helpers/components.test.ts +44 -0
  80. package/src/server/plugins/engine/components/helpers/components.ts +10 -0
  81. package/src/server/plugins/engine/components/helpers/geospatial.test.js +55 -0
  82. package/src/server/plugins/engine/components/helpers/geospatial.ts +93 -0
  83. package/src/server/plugins/engine/components/index.ts +1 -0
  84. package/src/server/plugins/engine/models/FormModel.ts +0 -4
  85. package/src/server/plugins/engine/pageControllers/PageController.ts +2 -0
  86. package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +2 -6
  87. package/src/server/plugins/engine/pageControllers/helpers/state.test.ts +80 -16
  88. package/src/server/plugins/engine/pageControllers/helpers/state.ts +57 -17
  89. package/src/server/plugins/engine/pageControllers/helpers/submission.test.ts +74 -0
  90. package/src/server/plugins/engine/pageControllers/helpers/submission.ts +17 -1
  91. package/src/server/plugins/engine/pageControllers/validationOptions.ts +3 -1
  92. package/src/server/plugins/engine/routes/index.test.ts +4 -2
  93. package/src/server/plugins/engine/routes/index.ts +13 -1
  94. package/src/server/plugins/engine/types.ts +77 -4
  95. package/src/server/plugins/engine/views/components/geospatialfield.html +7 -0
  96. package/src/server/plugins/nunjucks/context.test.js +2 -3
  97. package/src/server/routes/types.ts +4 -2
  98. package/src/server/services/cacheService.ts +2 -0
@@ -1,352 +1,15 @@
1
- // @ts-expect-error - no types
2
- import OsGridRef, { LatLon } from 'geodesy/osgridref.js'
1
+ import {
2
+ EVENTS,
3
+ centerMap,
4
+ createMap,
5
+ defaultConfig,
6
+ eastingNorthingToLatLong,
7
+ latLongToEastingNorthing,
8
+ latLongToOsGridRef,
9
+ osGridRefToLatLong
10
+ } from '~/src/client/javascripts/map.js'
3
11
 
4
- /**
5
- * Converts lat long to easting and northing
6
- * @param {object} param
7
- * @param {number} param.lat
8
- * @param {number} param.long
9
- * @returns {{ easting: number, northing: number }}
10
- */
11
- function latLongToEastingNorthing({ lat, long }) {
12
- const point = new LatLon(lat, long)
13
-
14
- return point.toOsGrid()
15
- }
16
-
17
- /**
18
- * Converts easting and northing to lat long
19
- * @param {object} param
20
- * @param {number} param.easting
21
- * @param {number} param.northing
22
- * @returns {{ lat: number, long: number }}
23
- */
24
- function eastingNorthingToLatLong({ easting, northing }) {
25
- const point = new OsGridRef(easting, northing)
26
- const latLong = point.toLatLon()
27
-
28
- return { lat: latLong.latitude, long: latLong.longitude }
29
- }
30
-
31
- /**
32
- * Converts lat long to an ordnance survey grid reference
33
- * @param {object} param
34
- * @param {number} param.lat
35
- * @param {number} param.long
36
- * @returns {string}
37
- */
38
- function latLongToOsGridRef({ lat, long }) {
39
- const point = new LatLon(lat, long)
40
-
41
- return point.toOsGrid().toString()
42
- }
43
-
44
- /**
45
- * Converts an ordnance survey grid reference to lat long
46
- * @param {string} osGridRef
47
- * @returns {{ lat: number, long: number }}
48
- */
49
- function osGridRefToLatLong(osGridRef) {
50
- const point = OsGridRef.parse(osGridRef)
51
- const latLong = point.toLatLon()
52
-
53
- return { lat: latLong.latitude, long: latLong.longitude }
54
- }
55
-
56
- // Center of UK
57
- const DEFAULT_LAT = 53.825564
58
- const DEFAULT_LONG = -2.421975
59
-
60
- /** @type {InteractiveMapInitConfig} */
61
- const defaultConfig = {
62
- zoom: '6',
63
- center: [DEFAULT_LONG, DEFAULT_LAT]
64
- }
65
-
66
- const COMPANY_SYMBOL_CODE = 169
67
12
  const LOCATION_FIELD_SELECTOR = 'input.govuk-input'
68
- const EVENTS = {
69
- interactMarkerChange: 'interact:markerchange'
70
- }
71
-
72
- const defaultData = {
73
- VTS_OUTDOOR_URL: '/api/maps/vts/OS_VTS_3857_Outdoor.json',
74
- VTS_DARK_URL: '/api/maps/vts/OS_VTS_3857_Dark.json',
75
- VTS_BLACK_AND_WHITE_URL: '/api/maps/vts/OS_VTS_3857_Black_and_White.json'
76
- }
77
-
78
- /**
79
- * Make a form submit handler that only allows submissions from allowed buttons
80
- * @param {HTMLButtonElement[]} buttons - the form buttons to allow submissions
81
- */
82
- export function formSubmitFactory(buttons) {
83
- /**
84
- * The submit handler
85
- * @param {SubmitEvent} e
86
- */
87
- const onFormSubmit = function (e) {
88
- if (
89
- !(e.submitter instanceof HTMLButtonElement) ||
90
- !buttons.includes(e.submitter)
91
- ) {
92
- e.preventDefault()
93
- }
94
- }
95
-
96
- return onFormSubmit
97
- }
98
-
99
- /**
100
- * Initialise location maps
101
- * @param {Partial<MapsEnvironmentConfig>} config - the map configuration
102
- */
103
- export function initMaps(config = {}) {
104
- const {
105
- assetPath = '/assets',
106
- apiPath = '/form/api',
107
- data = defaultData
108
- } = config
109
- const locations = document.querySelectorAll('.app-location-field')
110
-
111
- // TODO: Fix this in `interactive-map`
112
- // If there are location components on the page fix up the main form submit
113
- // handler so it doesn't fire when using the integrated map search feature
114
- if (locations.length) {
115
- const form = locations[0].closest('form')
116
-
117
- if (form === null) {
118
- return
119
- }
120
-
121
- const buttons = Array.from(form.querySelectorAll('button'))
122
- form.addEventListener('submit', formSubmitFactory(buttons), false)
123
- }
124
-
125
- locations.forEach((location, index) => {
126
- processLocation({ assetPath, apiPath, data }, location, index)
127
- })
128
- }
129
-
130
- /**
131
- * OS API request proxy factory
132
- * @param {string} apiPath - the root API path
133
- */
134
- export function makeTileRequestTransformer(apiPath) {
135
- /**
136
- * Proxy OS API requests via our server
137
- * @param {string} url - the request URL
138
- * @param {string} resourceType - the resource type
139
- */
140
- return function transformTileRequest(url, resourceType) {
141
- if (url.startsWith('https://api.os.uk')) {
142
- if (resourceType === 'Tile') {
143
- return {
144
- url: url.replace(
145
- 'https://api.os.uk/maps/vector/v1/vts',
146
- `${window.location.origin}${apiPath}`
147
- ),
148
- headers: {}
149
- }
150
- }
151
-
152
- if (resourceType !== 'Style') {
153
- return {
154
- url: `${apiPath}/map-proxy?url=${encodeURIComponent(url)}`,
155
- headers: {}
156
- }
157
- }
158
- }
159
-
160
- const spritesPath =
161
- 'https://raw.githubusercontent.com/OrdnanceSurvey/OS-Vector-Tile-API-Stylesheets/main'
162
-
163
- // Proxy sprite requests
164
- if (url.startsWith(spritesPath)) {
165
- const path = url.substring(spritesPath.length)
166
- return {
167
- url: `${apiPath}/maps/vts${path}`,
168
- headers: {}
169
- }
170
- }
171
-
172
- return { url, headers: {} }
173
- }
174
- }
175
-
176
- /**
177
- * Processes a location field to add map capability
178
- * @param {MapsEnvironmentConfig} config - the location field element
179
- * @param {Element} location - the location field element
180
- * @param {*} index - the 0-based index
181
- */
182
- function processLocation(config, location, index) {
183
- if (!(location instanceof HTMLDivElement)) {
184
- return
185
- }
186
-
187
- const locationInputs = location.querySelector('.app-location-field-inputs')
188
- if (!(locationInputs instanceof HTMLDivElement)) {
189
- return
190
- }
191
- const locationType = location.dataset.locationtype
192
-
193
- // Check for support
194
- const supportedLocations = [
195
- 'latlongfield',
196
- 'eastingnorthingfield',
197
- 'osgridreffield'
198
- ]
199
- if (!locationType || !supportedLocations.includes(locationType)) {
200
- return
201
- }
202
-
203
- const mapContainer = document.createElement('div')
204
- const mapId = `map_${index}`
205
-
206
- mapContainer.setAttribute('id', mapId)
207
- mapContainer.setAttribute('class', 'map-container')
208
-
209
- const initConfig = getInitMapConfig(location) ?? defaultConfig
210
-
211
- locationInputs.after(mapContainer)
212
-
213
- const { map, interactPlugin } = createMap(mapId, initConfig, config)
214
-
215
- map.on(
216
- 'map:ready',
217
- /**
218
- * Callback function which fires when the map is ready
219
- * @param {object} e - the event
220
- * @param {MapLibreMap} e.map - the map provider instance
221
- */
222
- function onMapReady(e) {
223
- switch (locationType) {
224
- case 'latlongfield':
225
- bindLatLongField(location, map, e.map)
226
- break
227
- case 'eastingnorthingfield':
228
- bindEastingNorthingField(location, map, e.map)
229
- break
230
- case 'osgridreffield':
231
- bindOsGridRefField(location, map, e.map)
232
- break
233
- default:
234
- throw new Error('Not implemented')
235
- }
236
-
237
- // Add info panel
238
- map.addPanel('info', {
239
- showLabel: true,
240
- label: 'How to use the map',
241
- mobile: {
242
- slot: 'bottom',
243
- initiallyOpen: true,
244
- dismissable: true,
245
- modal: false
246
- },
247
- tablet: {
248
- slot: 'bottom',
249
- initiallyOpen: true,
250
- dismissable: true,
251
- modal: false
252
- },
253
- desktop: {
254
- slot: 'bottom',
255
- initiallyOpen: true,
256
- dismissable: true,
257
- modal: false
258
- },
259
- html: 'If using a map click on a point to update the location.<br><br>If using a keyboard, navigate to the point, centering the crosshair at the location and press enter.'
260
- })
261
-
262
- // Enable the interact plugin
263
- interactPlugin.enable()
264
- }
265
- )
266
- }
267
-
268
- /**
269
- * Create a Defra map instance
270
- * @param {string} mapId - the map id
271
- * @param {InteractiveMapInitConfig} initConfig - the map initial configuration
272
- * @param {MapsEnvironmentConfig} mapsConfig - the map environment params
273
- */
274
- function createMap(mapId, initConfig, mapsConfig) {
275
- const { assetPath, apiPath, data = defaultData } = mapsConfig
276
- const logoAltText = 'Ordnance survey logo'
277
-
278
- // @ts-expect-error - Defra namespace currently comes from UMD support files
279
- const defra = window.defra
280
-
281
- const interactPlugin = defra.interactPlugin({
282
- dataLayers: [],
283
- markerColor: { outdoor: '#ff0000', dark: '#00ff00' },
284
- interactionMode: 'marker',
285
- multiSelect: false
286
- })
287
-
288
- /** @type {InteractiveMap} */
289
- const map = new defra.InteractiveMap(mapId, {
290
- ...initConfig,
291
- mapProvider: defra.maplibreProvider(),
292
- reverseGeocodeProvider: defra.openNamesProvider({
293
- url: `${apiPath}/reverse-geocode-proxy?easting={easting}&northing={northing}`
294
- }),
295
- behaviour: 'inline',
296
- minZoom: 6,
297
- maxZoom: 18,
298
- containerHeight: '400px',
299
- enableZoomControls: true,
300
- transformRequest: makeTileRequestTransformer(apiPath),
301
- plugins: [
302
- defra.mapStylesPlugin({
303
- mapStyles: [
304
- {
305
- id: 'outdoor',
306
- label: 'Outdoor',
307
- url: data.VTS_OUTDOOR_URL,
308
- thumbnail: `${assetPath}/interactive-map/assets/images/outdoor-map-thumb.jpg`,
309
- logo: `${assetPath}/interactive-map/assets/images/os-logo.svg`,
310
- logoAltText,
311
- attribution: `Contains OS data ${String.fromCodePoint(COMPANY_SYMBOL_CODE)} Crown copyright and database rights ${new Date().getFullYear()}`,
312
- backgroundColor: '#f5f5f0'
313
- },
314
- {
315
- id: 'dark',
316
- label: 'Dark',
317
- url: data.VTS_DARK_URL,
318
- mapColorScheme: 'dark',
319
- appColorScheme: 'dark',
320
- thumbnail: `${assetPath}/interactive-map/assets/images/dark-map-thumb.jpg`,
321
- logo: `${assetPath}/interactive-map/assets/images/os-logo-white.svg`,
322
- logoAltText,
323
- attribution: `Contains OS data ${String.fromCodePoint(COMPANY_SYMBOL_CODE)} Crown copyright and database rights ${new Date().getFullYear()}`
324
- },
325
- {
326
- id: 'black-and-white',
327
- label: 'Black/White',
328
- url: data.VTS_BLACK_AND_WHITE_URL,
329
- thumbnail: `${assetPath}/interactive-map/assets/images/black-and-white-map-thumb.jpg`,
330
- logo: `${assetPath}/interactive-map/assets/images/os-logo-black.svg`,
331
- logoAltText,
332
- attribution: `Contains OS data ${String.fromCodePoint(COMPANY_SYMBOL_CODE)} Crown copyright and database rights ${new Date().getFullYear()}`
333
- }
334
- ]
335
- }),
336
- interactPlugin,
337
- defra.searchPlugin({
338
- osNamesURL: `${apiPath}/geocode-proxy?query={query}`,
339
- width: '300px',
340
- showMarker: false
341
- }),
342
- defra.scaleBarPlugin({
343
- units: 'metric'
344
- })
345
- ]
346
- })
347
-
348
- return { map, interactPlugin }
349
- }
350
13
 
351
14
  /**
352
15
  * Gets initial map config for a location field
@@ -719,56 +382,97 @@ function bindOsGridRefField(locationField, map, mapProvider) {
719
382
  }
720
383
 
721
384
  /**
722
- * Updates the marker position and moves the map view port the new location
723
- * @param {InteractiveMap} map - the map component instance (of InteractiveMap)
724
- * @param {MapLibreMap} mapProvider - the map provider instance (of MapLibreMap)
725
- * @param {MapCenter} center - the point
385
+ * Processes a location field to add map capability
386
+ * @param {MapsEnvironmentConfig} config - the location field element
387
+ * @param {Element} location - the location field element
388
+ * @param {number} index - the 0-based index
726
389
  */
727
- function centerMap(map, mapProvider, center) {
728
- // Move the 'location' marker to the new point
729
- map.addMarker('location', center)
390
+ export function processLocation(config, location, index) {
391
+ if (!(location instanceof HTMLDivElement)) {
392
+ return
393
+ }
730
394
 
731
- // Pan & zoom the map to the new valid location
732
- mapProvider.flyTo({
733
- center,
734
- zoom: 14,
735
- essential: true
736
- })
737
- }
395
+ const locationInputs = location.querySelector('.app-location-field-inputs')
396
+ if (!(locationInputs instanceof HTMLDivElement)) {
397
+ return
398
+ }
399
+ const locationType = location.dataset.locationtype
738
400
 
739
- /**
740
- * @typedef {object} InteractiveMap - an instance of a InteractiveMap
741
- * @property {Function} on - register callback listeners to map events
742
- * @property {Function} addPanel - adds a new panel to the map
743
- * @property {Function} addMarker - adds/updates a marker
744
- */
401
+ // Check for support
402
+ const supportedLocations = [
403
+ 'latlongfield',
404
+ 'eastingnorthingfield',
405
+ 'osgridreffield'
406
+ ]
407
+ if (!locationType || !supportedLocations.includes(locationType)) {
408
+ return
409
+ }
745
410
 
746
- /**
747
- * @typedef {object} MapLibreMap
748
- * @property {Function} flyTo - pans/zooms to a new location
749
- */
411
+ const mapContainer = document.createElement('div')
412
+ const mapId = `map_${index}`
750
413
 
751
- /**
752
- * @typedef {[number, number]} MapCenter - Map center point as [long, lat]
753
- */
414
+ mapContainer.setAttribute('id', mapId)
415
+ mapContainer.setAttribute('class', 'map-container')
754
416
 
755
- /**
756
- * @typedef {object} InteractiveMapInitConfig - additional config that can be provided to InteractiveMap
757
- * @property {string} zoom - the zoom level of the map
758
- * @property {MapCenter} center - the center point of the map
759
- * @property {{ id: string, coords: MapCenter}[]} [markers] - the markers to add to the map
760
- */
417
+ const initConfig = getInitMapConfig(location) ?? defaultConfig
761
418
 
762
- /**
763
- * @typedef {object} TileData
764
- * @property {string} VTS_OUTDOOR_URL - the outdoor tile URL
765
- * @property {string} VTS_DARK_URL - the dark tile URL
766
- * @property {string} VTS_BLACK_AND_WHITE_URL - the black and white tile URL
767
- */
419
+ locationInputs.after(mapContainer)
420
+
421
+ const { map, interactPlugin } = createMap(mapId, initConfig, config)
422
+
423
+ map.on(
424
+ EVENTS.mapReady,
425
+ /**
426
+ * Callback function which fires when the map is ready
427
+ * @param {object} e - the event
428
+ * @param {MapLibreMap} e.map - the map provider instance
429
+ */
430
+ function onMapReady(e) {
431
+ switch (locationType) {
432
+ case 'latlongfield':
433
+ bindLatLongField(location, map, e.map)
434
+ break
435
+ case 'eastingnorthingfield':
436
+ bindEastingNorthingField(location, map, e.map)
437
+ break
438
+ case 'osgridreffield':
439
+ bindOsGridRefField(location, map, e.map)
440
+ break
441
+ default:
442
+ throw new Error('Not implemented')
443
+ }
444
+
445
+ // Add info panel
446
+ map.addPanel('info', {
447
+ showLabel: true,
448
+ label: 'How to use the map',
449
+ mobile: {
450
+ slot: 'bottom',
451
+ open: true,
452
+ dismissible: true,
453
+ modal: false
454
+ },
455
+ tablet: {
456
+ slot: 'bottom',
457
+ open: true,
458
+ dismissible: true,
459
+ modal: false
460
+ },
461
+ desktop: {
462
+ slot: 'bottom',
463
+ open: true,
464
+ dismissible: true,
465
+ modal: false
466
+ },
467
+ html: 'If using a map click on a point to update the location.<br><br>If using a keyboard, navigate to the point, centering the crosshair at the location and press enter.'
468
+ })
469
+
470
+ // Enable the interact plugin
471
+ interactPlugin.enable()
472
+ }
473
+ )
474
+ }
768
475
 
769
476
  /**
770
- * @typedef {object} MapsEnvironmentConfig
771
- * @property {string} assetPath - the root asset path
772
- * @property {string} apiPath - the root API path
773
- * @property {TileData} data - the tile data config
477
+ * @import { InteractiveMap, InteractiveMapInitConfig, MapCenter, MapLibreMap, MapsEnvironmentConfig } from '~/src/client/javascripts/map.js'
774
478
  */