@defra/interactive-map 0.0.39-alpha → 0.0.41-alpha

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 (387) hide show
  1. package/dist/css/index.css +1 -1
  2. package/dist/esm/im-core.js +1 -1
  3. package/dist/esm/im-shell.js +1 -1
  4. package/dist/umd/im-core.js +1 -1
  5. package/dist/umd/index.js +1 -1
  6. package/docs/api/control-definition.md +9 -1
  7. package/docs/api/slots.md +26 -5
  8. package/docs/api.md +4 -4
  9. package/docs/assets/images/slot-map.svg +61 -262
  10. package/docs/examples/draw-tools.mdx +3 -3
  11. package/docs/plugins/draw.md +80 -17
  12. package/docs/plugins/search.md +1 -1
  13. package/govuk-prototype-kit.config.json +2 -0
  14. package/jest.setup.js +5 -0
  15. package/package.json +9 -1
  16. package/plugins/beta/draw-es/dist/esm/im-draw-es-plugin.js +1 -1
  17. package/plugins/beta/draw-ml/dist/esm/im-draw-ml-plugin.js +1 -1
  18. package/plugins/beta/draw-ml/dist/umd/im-draw-ml-plugin.js +1 -1
  19. package/plugins/beta/draw-ol/dist/esm/im-draw-ol-plugin.js +1 -1
  20. package/plugins/beta/map-styles/dist/esm/im-map-styles-plugin.js +1 -1
  21. package/plugins/beta/map-styles/dist/umd/im-map-styles-plugin.js +1 -1
  22. package/plugins/beta/map-styles/dist/umd/index.js +1 -1
  23. package/plugins/datasets/dist/css/index.css +1 -1
  24. package/plugins/datasets/dist/esm/esriLayerAdapter.js +1 -1
  25. package/plugins/datasets/dist/esm/im-datasets-ml-adapter.js +1 -1
  26. package/plugins/datasets/dist/esm/im-datasets-plugin.js +1 -1
  27. package/plugins/datasets/dist/umd/im-datasets-esri-adapter.js +1 -1
  28. package/plugins/datasets/dist/umd/im-datasets-ml-adapter.js +1 -1
  29. package/plugins/datasets/dist/umd/im-datasets-plugin.js +1 -1
  30. package/plugins/datasets/dist/umd/index.js +1 -1
  31. package/plugins/datasets/src/adapters/esri/esriLayerAdapter.js +2 -3
  32. package/plugins/datasets/src/adapters/esri/esriLayerAdapter.test.js +175 -0
  33. package/plugins/datasets/src/adapters/esri/registry/esriDataset.js +1 -1
  34. package/plugins/datasets/src/adapters/esri/registry/esriDataset.test.js +55 -0
  35. package/plugins/datasets/src/adapters/loadLayerAdapter.js +1 -1
  36. package/plugins/datasets/src/adapters/loadLayerAdapter.test.js +61 -0
  37. package/plugins/datasets/src/adapters/maplibre/maplibreLayerAdapter.js +1 -3
  38. package/plugins/datasets/src/adapters/maplibre/maplibreLayerAdapter.test.js +17 -3
  39. package/plugins/datasets/src/api/setOpacity.test.js +9 -0
  40. package/plugins/datasets/src/components/LayersMenu/LayersMenu.jsx +10 -25
  41. package/plugins/datasets/src/components/LayersMenu/LayersMenu.test.jsx +0 -42
  42. package/plugins/datasets/src/datasets.scss +0 -1
  43. package/plugins/datasets/src/fetch/createDynamicSource.js +135 -129
  44. package/plugins/datasets/src/fetch/createDynamicSource.test.js +318 -0
  45. package/plugins/datasets/src/fetch/fetchGeoJSON.test.js +83 -0
  46. package/plugins/datasets/src/index.test.js +36 -0
  47. package/plugins/datasets/src/initialise/DatasetsInit.jsx +17 -7
  48. package/plugins/datasets/src/initialise/DatasetsInit.test.jsx +262 -0
  49. package/plugins/datasets/src/initialise/initialiseDatasets.js +16 -5
  50. package/plugins/datasets/src/initialise/initialiseDatasets.test.js +42 -0
  51. package/plugins/datasets/src/manifest.js +0 -38
  52. package/plugins/datasets/src/manifest.test.js +49 -0
  53. package/plugins/datasets/src/reducers/datasetsToMenu.test.js +54 -1
  54. package/plugins/datasets/src/reducers/pluginState.js +3 -16
  55. package/plugins/datasets/src/reducers/pluginState.test.js +23 -0
  56. package/plugins/datasets/src/registry/dataset.js +15 -4
  57. package/plugins/datasets/src/registry/dataset.test.js +61 -0
  58. package/plugins/datasets/src/registry/datasetRegistry.js +12 -9
  59. package/plugins/datasets/src/registry/datasetRegistry.test.js +17 -5
  60. package/plugins/datasets/src/registry/globalDataset.js +0 -3
  61. package/plugins/datasets/src/registry/isVisibleWhen.js +6 -3
  62. package/plugins/datasets/src/registry/isVisibleWhen.test.js +11 -1
  63. package/plugins/datasets/src/utils/bbox.test.js +125 -0
  64. package/plugins/draw/dist/esm/im-draw-ml-adapter.js +1 -1
  65. package/plugins/draw/dist/esm/im-draw-ol-adapter.js +1 -1
  66. package/plugins/draw/dist/esm/im-draw-plugin.js +1 -1
  67. package/plugins/draw/dist/esm/index.js +1 -1
  68. package/plugins/draw/dist/umd/im-draw-ml-adapter.js +2 -1
  69. package/plugins/draw/dist/umd/im-draw-ml-adapter.js.LICENSE.txt +1 -0
  70. package/plugins/draw/dist/umd/im-draw-ol-adapter.js +1 -1
  71. package/plugins/draw/dist/umd/im-draw-plugin.js +1 -1
  72. package/plugins/draw/dist/umd/index.js +1 -1
  73. package/plugins/draw/src/DrawInit.jsx +12 -4
  74. package/plugins/draw/src/DrawInit.test.jsx +51 -10
  75. package/plugins/draw/src/adapters/maplibre/MaplibreDrawAdapter.js +92 -12
  76. package/plugins/draw/src/adapters/maplibre/MaplibreDrawAdapter.test.js +246 -4
  77. package/plugins/draw/src/adapters/maplibre/mapboxDraw.js +109 -14
  78. package/plugins/draw/src/adapters/maplibre/mapboxDraw.test.js +174 -11
  79. package/plugins/draw/src/adapters/maplibre/modes/drawMode/clickHandlers.test.js +12 -0
  80. package/plugins/draw/src/adapters/maplibre/modes/drawMode/lifecycle.js +9 -1
  81. package/plugins/draw/src/adapters/maplibre/modes/drawMode/lifecycle.test.js +24 -3
  82. package/plugins/draw/src/adapters/maplibre/modes/drawMode/pointerHandlers.js +1 -1
  83. package/plugins/draw/src/adapters/maplibre/modes/drawMode/pointerHandlers.test.js +1 -1
  84. package/plugins/draw/src/adapters/maplibre/modes/drawPointMode.js +194 -0
  85. package/plugins/draw/src/adapters/maplibre/modes/drawPointMode.test.js +457 -0
  86. package/plugins/draw/src/adapters/maplibre/modes/editPointMode/__helpers__/harness.js +102 -0
  87. package/plugins/draw/src/adapters/maplibre/modes/editPointMode/keyboardHandlers.js +82 -0
  88. package/plugins/draw/src/adapters/maplibre/modes/editPointMode/keyboardHandlers.test.js +83 -0
  89. package/plugins/draw/src/adapters/maplibre/modes/editPointMode/pointOperations.js +55 -0
  90. package/plugins/draw/src/adapters/maplibre/modes/editPointMode/pointOperations.test.js +62 -0
  91. package/plugins/draw/src/adapters/maplibre/modes/editPointMode/pointerHandlers.js +138 -0
  92. package/plugins/draw/src/adapters/maplibre/modes/editPointMode/pointerHandlers.test.js +197 -0
  93. package/plugins/draw/src/adapters/maplibre/modes/editPointMode/touchHandlers.js +92 -0
  94. package/plugins/draw/src/adapters/maplibre/modes/editPointMode/touchHandlers.test.js +101 -0
  95. package/plugins/draw/src/adapters/maplibre/modes/editPointMode/undoHandlers.js +46 -0
  96. package/plugins/draw/src/adapters/maplibre/modes/editPointMode/undoHandlers.test.js +42 -0
  97. package/plugins/draw/src/adapters/maplibre/modes/editPointMode.js +151 -0
  98. package/plugins/draw/src/adapters/maplibre/modes/editPointMode.test.js +156 -0
  99. package/plugins/draw/src/adapters/maplibre/modes/editVertexMode/keyboardHandlers.js +5 -28
  100. package/plugins/draw/src/adapters/maplibre/modes/editVertexMode/keyboardHandlers.test.js +24 -39
  101. package/plugins/draw/src/adapters/maplibre/modes/editVertexMode/pointerHandlers.js +4 -5
  102. package/plugins/draw/src/adapters/maplibre/modes/editVertexMode/touchHandlers.js +20 -23
  103. package/plugins/draw/src/adapters/maplibre/modes/editVertexMode/touchHandlers.test.js +25 -5
  104. package/plugins/draw/src/adapters/maplibre/modes/editVertexMode/undoHandlers.js +6 -36
  105. package/plugins/draw/src/adapters/maplibre/modes/editVertexMode/undoHandlers.test.js +7 -49
  106. package/plugins/draw/src/adapters/maplibre/modes/editVertexMode/vertexOperations.js +4 -54
  107. package/plugins/draw/src/adapters/maplibre/modes/editVertexMode/vertexOperations.test.js +8 -33
  108. package/plugins/draw/src/adapters/maplibre/modes/editVertexMode.js +29 -72
  109. package/plugins/draw/src/adapters/maplibre/modes/editVertexMode.test.js +11 -4
  110. package/plugins/draw/src/adapters/maplibre/pointSymbolImages.js +158 -0
  111. package/plugins/draw/src/adapters/maplibre/pointSymbolImages.test.js +314 -0
  112. package/plugins/draw/src/adapters/maplibre/snap/prototypePatches.js +6 -1
  113. package/plugins/draw/src/adapters/maplibre/snap/prototypePatches.test.js +21 -0
  114. package/plugins/draw/src/adapters/maplibre/snap/snapInstance.js +6 -2
  115. package/plugins/draw/src/adapters/maplibre/snap/snapInstance.test.js +12 -0
  116. package/plugins/draw/src/adapters/maplibre/styles.js +38 -11
  117. package/plugins/draw/src/adapters/maplibre/styles.test.js +39 -0
  118. package/plugins/draw/src/adapters/maplibre/utils/editModeEvents.js +79 -0
  119. package/plugins/draw/src/adapters/maplibre/utils/editModeEvents.test.js +135 -0
  120. package/plugins/draw/src/adapters/maplibre/utils/geometryValidation.js +42 -0
  121. package/plugins/draw/src/adapters/maplibre/utils/geometryValidation.test.js +85 -0
  122. package/plugins/draw/src/adapters/maplibre/utils/keyboardShortcuts.js +34 -0
  123. package/plugins/draw/src/adapters/maplibre/utils/keyboardShortcuts.test.js +78 -0
  124. package/plugins/draw/src/adapters/maplibre/utils/snapHelpers.js +16 -3
  125. package/plugins/draw/src/adapters/maplibre/utils/snapHelpers.test.js +21 -3
  126. package/plugins/draw/src/adapters/maplibre/utils/snapMovement.js +59 -0
  127. package/plugins/draw/src/adapters/maplibre/utils/snapMovement.test.js +73 -0
  128. package/plugins/draw/src/adapters/maplibre/utils/touchDragMath.js +33 -0
  129. package/plugins/draw/src/adapters/maplibre/utils/touchDragMath.test.js +70 -0
  130. package/plugins/draw/src/adapters/openlayers/OLDrawAdapter.js +27 -2
  131. package/plugins/draw/src/adapters/openlayers/OLDrawAdapter.test.js +93 -0
  132. package/plugins/draw/src/adapters/openlayers/__helpers__/harness.js +9 -0
  133. package/plugins/draw/src/adapters/openlayers/core/OLDrawManager.js +19 -1
  134. package/plugins/draw/src/adapters/openlayers/core/OLDrawManager.test.js +34 -1
  135. package/plugins/draw/src/adapters/openlayers/core/styles.js +73 -1
  136. package/plugins/draw/src/adapters/openlayers/core/styles.test.js +122 -3
  137. package/plugins/draw/src/adapters/openlayers/draw/DrawMode.js +1 -0
  138. package/plugins/draw/src/adapters/openlayers/draw/DrawMode.test.js +27 -1
  139. package/plugins/draw/src/adapters/openlayers/draw/drawInput.js +24 -4
  140. package/plugins/draw/src/adapters/openlayers/draw/drawInput.test.js +47 -3
  141. package/plugins/draw/src/adapters/openlayers/edit/EditMode.js +1 -1
  142. package/plugins/draw/src/adapters/openlayers/edit/EditMode.test.js +32 -1
  143. package/plugins/draw/src/adapters/openlayers/edit/keyboardHandler.js +9 -5
  144. package/plugins/draw/src/adapters/openlayers/edit/keyboardHandler.test.js +34 -1
  145. package/plugins/draw/src/adapters/openlayers/edit/modifyInteraction.js +5 -3
  146. package/plugins/draw/src/adapters/openlayers/edit/modifyInteraction.test.js +11 -0
  147. package/plugins/draw/src/adapters/openlayers/edit/nudge.js +12 -5
  148. package/plugins/draw/src/adapters/openlayers/edit/nudge.test.js +26 -3
  149. package/plugins/draw/src/adapters/openlayers/edit/touchHandler.js +18 -13
  150. package/plugins/draw/src/adapters/openlayers/edit/touchHandler.test.js +46 -1
  151. package/plugins/draw/src/adapters/openlayers/olDraw.js +11 -4
  152. package/plugins/draw/src/adapters/openlayers/olDraw.test.js +48 -6
  153. package/plugins/draw/src/adapters/openlayers/point/drawPointMode.js +156 -0
  154. package/plugins/draw/src/adapters/openlayers/point/drawPointMode.test.js +246 -0
  155. package/plugins/draw/src/adapters/openlayers/point/editPointMode.js +267 -0
  156. package/plugins/draw/src/adapters/openlayers/point/editPointMode.test.js +327 -0
  157. package/plugins/draw/src/adapters/openlayers/point/pointDragInteraction.js +71 -0
  158. package/plugins/draw/src/adapters/openlayers/point/pointOps.js +34 -0
  159. package/plugins/draw/src/adapters/openlayers/point/pointOps.test.js +32 -0
  160. package/plugins/draw/src/adapters/openlayers/point/pointSelectionState.js +82 -0
  161. package/plugins/draw/src/adapters/openlayers/point/pointSelectionState.test.js +107 -0
  162. package/plugins/draw/src/adapters/openlayers/point/pointSymbolImages.js +83 -0
  163. package/plugins/draw/src/adapters/openlayers/point/pointSymbolImages.test.js +214 -0
  164. package/plugins/draw/src/adapters/openlayers/snap/snapIndicator.js +3 -1
  165. package/plugins/draw/src/adapters/openlayers/snap/snapInteraction.js +6 -9
  166. package/plugins/draw/src/adapters/openlayers/snap/snapInteraction.test.js +15 -4
  167. package/plugins/draw/src/adapters/openlayers/utils/olCoords.js +1 -1
  168. package/plugins/draw/src/api/addFeature.js +16 -1
  169. package/plugins/draw/src/api/addFeature.test.js +62 -5
  170. package/plugins/draw/src/api/editFeature.js +7 -4
  171. package/plugins/draw/src/api/editFeature.test.js +16 -0
  172. package/plugins/draw/src/api/newPoint.js +42 -0
  173. package/plugins/draw/src/api/newPoint.test.js +117 -0
  174. package/plugins/draw/src/api/setStyle.js +43 -0
  175. package/plugins/draw/src/api/setStyle.test.js +75 -0
  176. package/plugins/draw/src/events.js +21 -14
  177. package/plugins/draw/src/events.test.js +15 -1
  178. package/plugins/draw/src/manifest.js +18 -6
  179. package/plugins/draw/src/manifest.test.js +32 -1
  180. package/plugins/draw/src/reducer.test.js +7 -0
  181. package/plugins/draw/src/utils/stripInternalProperties.js +19 -0
  182. package/plugins/draw/src/utils/stripInternalProperties.test.js +50 -0
  183. package/plugins/draw/src/utils/symbolKeys.js +5 -0
  184. package/plugins/draw/src/validation/liveDrawChecks.test.js +54 -0
  185. package/plugins/draw/src/validation/liveStroke.test.js +64 -1
  186. package/plugins/interact/dist/esm/im-interact-plugin.js +1 -1
  187. package/plugins/interact/dist/umd/im-interact-plugin.js +1 -1
  188. package/plugins/interact/dist/umd/index.js +1 -1
  189. package/plugins/interact/src/hooks/useCrossHairVisibility.js +12 -4
  190. package/plugins/interact/src/hooks/useCrossHairVisibility.test.js +88 -1
  191. package/plugins/interact/src/hooks/useHighlightSync.js +33 -12
  192. package/plugins/interact/src/hooks/useHighlightSync.test.js +96 -25
  193. package/plugins/interact/src/utils/featureQueries.js +18 -0
  194. package/plugins/interact/src/utils/featureQueries.test.js +15 -0
  195. package/plugins/interact/src/utils/spatial.js +9 -3
  196. package/plugins/interact/src/utils/spatial.test.js +12 -1
  197. package/plugins/map-key/dist/css/index.css +62 -0
  198. package/plugins/map-key/dist/esm/im-map-key-plugin.js +1 -0
  199. package/plugins/map-key/dist/esm/index.js +1 -0
  200. package/plugins/map-key/dist/umd/im-map-key-plugin.js +2 -0
  201. package/plugins/map-key/dist/umd/im-map-key-plugin.js.LICENSE.txt +1 -0
  202. package/plugins/map-key/dist/umd/index.js +2 -0
  203. package/plugins/map-key/dist/umd/index.js.LICENSE.txt +1 -0
  204. package/plugins/map-key/package.json +28 -0
  205. package/plugins/map-key/src/components/Key/EmptyKey.jsx +7 -0
  206. package/plugins/{datasets → map-key}/src/components/Key/EmptyKey.test.jsx +2 -2
  207. package/plugins/map-key/src/components/Key/Key.jsx +41 -0
  208. package/plugins/{datasets → map-key}/src/components/Key/Key.module.scss +15 -14
  209. package/plugins/map-key/src/components/Key/Key.test.jsx +73 -0
  210. package/plugins/map-key/src/components/Key/KeyGroupItem.jsx +16 -0
  211. package/plugins/map-key/src/components/Key/KeyGroupItem.test.jsx +53 -0
  212. package/plugins/map-key/src/components/Key/KeyItem.jsx +29 -0
  213. package/plugins/map-key/src/components/Key/KeyItem.test.jsx +67 -0
  214. package/plugins/map-key/src/components/Key/KeySvg.jsx +42 -0
  215. package/plugins/{datasets → map-key}/src/components/Key/KeySvg.test.jsx +14 -12
  216. package/plugins/map-key/src/components/Key/KeySvgLine.jsx +28 -0
  217. package/plugins/{datasets → map-key}/src/components/Key/KeySvgLine.test.jsx +1 -1
  218. package/plugins/map-key/src/components/Key/KeySvgPattern.jsx +23 -0
  219. package/plugins/{datasets → map-key}/src/components/Key/KeySvgPattern.test.jsx +2 -2
  220. package/plugins/map-key/src/components/Key/KeySvgRect.jsx +33 -0
  221. package/plugins/{datasets → map-key}/src/components/Key/KeySvgRect.test.jsx +1 -1
  222. package/plugins/map-key/src/components/Key/KeySvgSymbol.jsx +27 -0
  223. package/plugins/{datasets → map-key}/src/components/Key/KeySvgSymbol.test.jsx +5 -6
  224. package/plugins/map-key/src/components/Key/MapKey.jsx +50 -0
  225. package/plugins/map-key/src/components/Key/MapKey.test.jsx +130 -0
  226. package/plugins/{datasets → map-key}/src/components/Key/svgProperties.js +2 -2
  227. package/plugins/{datasets → map-key}/src/components/Key/svgProperties.test.js +2 -2
  228. package/plugins/map-key/src/index.js +13 -0
  229. package/plugins/map-key/src/index.test.js +31 -0
  230. package/plugins/map-key/src/initialise/MapKeyInit.jsx +15 -0
  231. package/plugins/map-key/src/initialise/MapKeyInit.test.jsx +39 -0
  232. package/plugins/map-key/src/manifest.js +30 -0
  233. package/plugins/map-key/src/manifest.test.js +63 -0
  234. package/plugins/map-key/src/mapKey.scss +4 -0
  235. package/plugins/map-key/src/registry/getDatasetRegistry.js +6 -0
  236. package/plugins/map-key/src/registry/getDatasetRegistry.test.js +23 -0
  237. package/plugins/map-key/src/registry/index.js +3 -0
  238. package/plugins/map-key/src/registry/index.test.js +15 -0
  239. package/plugins/menu/dist/css/index.css +80 -0
  240. package/plugins/menu/dist/esm/im-menu-plugin.js +1 -0
  241. package/plugins/menu/dist/esm/index.js +1 -0
  242. package/plugins/menu/dist/umd/im-menu-plugin.js +1 -0
  243. package/plugins/menu/dist/umd/index.js +2 -0
  244. package/plugins/menu/dist/umd/index.js.LICENSE.txt +1 -0
  245. package/plugins/menu/package.json +28 -0
  246. package/plugins/menu/src/components/Menu/CheckboxGroupWrapper.jsx +21 -0
  247. package/plugins/menu/src/components/Menu/GroupLegend.jsx +17 -0
  248. package/plugins/menu/src/components/Menu/GroupLegend.test.jsx +68 -0
  249. package/plugins/menu/src/components/Menu/Menu.jsx +19 -0
  250. package/plugins/menu/src/components/Menu/Menu.module.scss +90 -0
  251. package/plugins/menu/src/components/Menu/Menu.test.jsx +161 -0
  252. package/plugins/menu/src/components/Menu/MenuCheckbox.jsx +35 -0
  253. package/plugins/menu/src/components/Menu/MenuCheckbox.test.jsx +93 -0
  254. package/plugins/menu/src/components/Menu/MenuGroup.jsx +11 -0
  255. package/plugins/{datasets/src/components/LayersMenu/LayersMenuRadio.jsx → menu/src/components/Menu/MenuRadio.jsx} +6 -4
  256. package/plugins/{datasets/src/components/LayersMenu/LayersMenuRadio.test.jsx → menu/src/components/Menu/MenuRadio.test.jsx} +18 -18
  257. package/plugins/menu/src/components/Menu/RadioGroupWrapper.jsx +32 -0
  258. package/plugins/{datasets/src/components/LayersMenu/LayersRadioGroupWrapper.test.jsx → menu/src/components/Menu/RadioGroupWrapper.test.jsx} +21 -21
  259. package/plugins/menu/src/components/Menu/useIdPrefix.jsx +4 -0
  260. package/plugins/menu/src/index.js +13 -0
  261. package/plugins/menu/src/index.test.js +31 -0
  262. package/plugins/menu/src/initialise/MenuInit.jsx +24 -0
  263. package/plugins/menu/src/initialise/MenuInit.test.jsx +50 -0
  264. package/plugins/menu/src/initialise/createMenu.js +10 -0
  265. package/plugins/menu/src/initialise/createMenu.test.js +37 -0
  266. package/plugins/menu/src/manifest.js +35 -0
  267. package/plugins/menu/src/manifest.test.js +63 -0
  268. package/plugins/menu/src/menu.scss +4 -0
  269. package/plugins/menu/src/reducers/menuStateReducer.test.js +38 -0
  270. package/plugins/menu/src/reducers/pluginState.js +35 -0
  271. package/plugins/menu/src/reducers/pluginState.test.js +57 -0
  272. package/plugins/menu/src/registry/getDatasetRegistry.js +9 -0
  273. package/plugins/menu/src/registry/getDatasetRegistry.test.js +23 -0
  274. package/plugins/menu/src/registry/index.js +3 -0
  275. package/plugins/menu/src/registry/index.test.js +15 -0
  276. package/plugins/menu/src/registry/isVisibleWhen.js +43 -0
  277. package/plugins/menu/src/registry/isVisibleWhen.test.js +48 -0
  278. package/plugins/search/dist/css/index.css +1 -1
  279. package/plugins/search/dist/esm/im-search-plugin.js +1 -1
  280. package/plugins/search/dist/esm/index.js +1 -1
  281. package/plugins/search/dist/umd/im-search-plugin.js +1 -1
  282. package/plugins/search/dist/umd/index.js +1 -1
  283. package/plugins/search/src/Search.jsx +7 -5
  284. package/plugins/search/src/components/Form/Form.module.scss +9 -20
  285. package/plugins/search/src/index.js +0 -1
  286. package/plugins/search/src/index.test.js +2 -4
  287. package/plugins/search/src/manifest.js +1 -1
  288. package/plugins/search/src/search.scss +17 -16
  289. package/providers/beta/openlayers/dist/esm/im-openlayers-provider.js +1 -1
  290. package/providers/beta/openlayers/dist/umd/im-openlayers-provider.js +1 -1
  291. package/providers/beta/openlayers/dist/umd/index.js +1 -1
  292. package/providers/beta/openlayers/src/openlayersProvider.js +4 -1
  293. package/providers/beta/openlayers/src/openlayersProvider.test.js +18 -0
  294. package/providers/beta/openlayers/src/utils/highlightFeatures.js +52 -5
  295. package/providers/beta/openlayers/src/utils/highlightFeatures.test.js +176 -0
  296. package/providers/beta/openlayers/src/utils/symbolImages.js +40 -0
  297. package/providers/beta/openlayers/src/utils/symbolImages.test.js +58 -0
  298. package/providers/maplibre/dist/esm/im-maplibre-provider.js +1 -1
  299. package/providers/maplibre/dist/umd/im-maplibre-provider.js +1 -1
  300. package/providers/maplibre/dist/umd/index.js +1 -1
  301. package/providers/maplibre/src/utils/drawLayerBuckets.js +14 -0
  302. package/providers/maplibre/src/utils/drawLayerBuckets.test.js +18 -0
  303. package/providers/maplibre/src/utils/highlightFeatures.js +80 -55
  304. package/providers/maplibre/src/utils/highlightFeatures.test.js +156 -17
  305. package/providers/maplibre/src/utils/hoverCursor.js +30 -14
  306. package/providers/maplibre/src/utils/hoverCursor.test.js +35 -0
  307. package/providers/maplibre/src/utils/patternImages.js +1 -1
  308. package/providers/maplibre/src/utils/symbolImages.js +41 -3
  309. package/providers/maplibre/src/utils/symbolImages.test.js +40 -6
  310. package/rollup.esm.mjs +11 -1
  311. package/sonar-project.properties +7 -1
  312. package/src/App/components/Actions/Actions.test.jsx +47 -0
  313. package/src/App/components/Attributions/Attributions.module.scss +10 -0
  314. package/src/App/components/Hints/Hints.jsx +7 -2
  315. package/src/App/components/Hints/Hints.test.jsx +13 -0
  316. package/src/App/components/KeyboardHelp/KeyboardHelp.jsx +2 -3
  317. package/src/App/components/KeyboardHelp/KeyboardHelp.test.jsx +3 -6
  318. package/src/App/components/{MoveControl/MoveControl.jsx → MoveControls/MoveControls.jsx} +10 -10
  319. package/src/App/components/{MoveControl/MoveControl.module.scss → MoveControls/MoveControls.module.scss} +60 -29
  320. package/src/App/components/{MoveControl/MoveControl.test.jsx → MoveControls/MoveControls.test.jsx} +48 -48
  321. package/src/App/components/Panel/Panel.jsx +18 -3
  322. package/src/App/components/Panel/Panel.module.scss +18 -8
  323. package/src/App/components/Panel/Panel.test.jsx +34 -0
  324. package/src/App/components/Tooltip/Tooltip.test.jsx +12 -14
  325. package/src/App/components/Viewport/Viewport.jsx +9 -1
  326. package/src/App/components/Viewport/Viewport.test.jsx +11 -0
  327. package/src/App/hooks/useFeatureItems.js +16 -7
  328. package/src/App/hooks/useFeatureItems.test.js +57 -0
  329. package/src/App/hooks/useLayoutMeasurements.js +95 -84
  330. package/src/App/hooks/useLayoutMeasurements.test.js +61 -1
  331. package/src/App/initialiseApp.js +11 -8
  332. package/src/App/initialiseApp.test.js +15 -3
  333. package/src/App/layout/Layout.jsx +12 -11
  334. package/src/App/layout/Layout.test.jsx +2 -0
  335. package/src/App/layout/layout.module.scss +31 -17
  336. package/src/App/registry/keyboardShortcutRegistry.js +25 -13
  337. package/src/App/registry/keyboardShortcutRegistry.test.js +49 -32
  338. package/src/App/registry/pluginRegistry.js +2 -3
  339. package/src/App/registry/pluginRegistry.test.js +16 -3
  340. package/src/App/renderer/HtmlElementHost.jsx +18 -5
  341. package/src/App/renderer/HtmlElementHost.test.jsx +54 -0
  342. package/src/App/renderer/mapButtons.js +28 -12
  343. package/src/App/renderer/mapButtons.test.js +17 -4
  344. package/src/App/renderer/mapControls.js +3 -1
  345. package/src/App/renderer/mapControls.test.js +16 -0
  346. package/src/App/renderer/mapPanels.js +44 -9
  347. package/src/App/renderer/mapPanels.test.js +51 -2
  348. package/src/App/renderer/orderItems.js +28 -0
  349. package/src/App/renderer/orderItems.test.js +50 -0
  350. package/src/App/renderer/slotAggregator.js +2 -18
  351. package/src/App/renderer/slotHelpers.js +3 -1
  352. package/src/App/renderer/slotHelpers.test.js +5 -0
  353. package/src/App/renderer/slots.js +3 -0
  354. package/src/App/store/AppProvider.jsx +4 -2
  355. package/src/App/store/appDispatchMiddleware.js +1 -1
  356. package/src/App/store/appDispatchMiddleware.test.js +8 -0
  357. package/src/InteractiveMap/InteractiveMap.js +8 -2
  358. package/src/InteractiveMap/InteractiveMap.test.js +20 -3
  359. package/src/config/appConfig.js +17 -15
  360. package/src/config/appConfig.test.js +22 -22
  361. package/src/config/defaults.js +3 -1
  362. package/src/config/events.js +2 -0
  363. package/src/config/mergeConfig.js +7 -0
  364. package/src/config/mergeConfig.test.js +20 -0
  365. package/src/scss/main.scss +1 -1
  366. package/src/scss/settings/_colors.scss +1 -0
  367. package/src/scss/settings/_dimensions.scss +2 -3
  368. package/src/scss/settings/_transition.scss +1 -1
  369. package/src/services/eventBus.js +44 -0
  370. package/src/services/eventBus.test.js +83 -0
  371. package/src/services/symbolRegistry.js +1 -1
  372. package/src/test-utils.js +5 -0
  373. package/src/types.js +25 -7
  374. package/webpack.umd.mjs +2 -0
  375. package/plugins/datasets/src/components/Key/EmptyKey.jsx +0 -7
  376. package/plugins/datasets/src/components/Key/Key.jsx +0 -50
  377. package/plugins/datasets/src/components/Key/KeyGroupItem.jsx +0 -18
  378. package/plugins/datasets/src/components/Key/KeyItem.jsx +0 -23
  379. package/plugins/datasets/src/components/Key/KeySvg.jsx +0 -22
  380. package/plugins/datasets/src/components/Key/KeySvgLine.jsx +0 -19
  381. package/plugins/datasets/src/components/Key/KeySvgPattern.jsx +0 -13
  382. package/plugins/datasets/src/components/Key/KeySvgRect.jsx +0 -22
  383. package/plugins/datasets/src/components/Key/KeySvgSymbol.jsx +0 -16
  384. package/plugins/datasets/src/components/LayersMenu/LayersRadioGroupWrapper.jsx +0 -41
  385. /package/plugins/{datasets → menu}/src/reducers/menuStateReducer.js +0 -0
  386. /package/{providers/maplibre/src → src}/utils/rasteriseToImageData.js +0 -0
  387. /package/{providers/maplibre/src → src}/utils/rasteriseToImageData.test.js +0 -0
@@ -16,13 +16,14 @@ const defaults = {
16
16
  containerHeight: '600px',
17
17
  deviceNotSupportedText: 'Your device is not supported. A map is available with a more up-to-date browser or device.',
18
18
  enableFullscreen: false,
19
- enableMoveControl: true,
19
+ enableMoveControls: true,
20
20
  enableZoomControls: true,
21
21
  genericErrorText: 'There was a problem loading the map. Please try again later.',
22
22
  hasExitButton: false,
23
23
  backAndContinue: null,
24
24
  hybridWidth: null, // Defaults to maxMobileWidth if not set
25
25
  keyboardHintText: '<span class="im-u-visually-hidden">Press </span><kbd>Shift</kbd> + <span class="im-u-visually-hidden">Question mark</span><kbd aria-hidden="true">?</kbd> <span class="im-u-visually-hidden">to view </span>keyboard shortcuts',
26
+ mapHintText: 'Press Tab to focus it. Keyboard commands are only available once it has focus.', // Visually hidden text for assitive technology
26
27
  mapLabel: 'Interactive map application',
27
28
  mapProvider: null,
28
29
  mapSize: 'small',
@@ -31,6 +32,7 @@ const defaults = {
31
32
  urlPosition: 'sync',
32
33
  maxMobileWidth: 640,
33
34
  minDesktopWidth: 835,
35
+ moveControlsHintText: 'A "Move and zoom controls" button is also available, opening further controls for moving and zooming.',
34
36
  nudgePanDelta: 5,
35
37
  nudgeZoomDelta: 0.1,
36
38
  panDelta: 100,
@@ -147,6 +147,8 @@ export const EVENTS = {
147
147
  MAP_SET_SIZE: 'map:setsize',
148
148
  /** @internal Set the accessible features list. Payload: { items: { id: string, label: string }[] } */
149
149
  MAP_SET_FEATURES: 'map:setfeatures',
150
+ /** @internal Suppress/restore the accessible features list. Payload: { suppressed: boolean } */
151
+ MAP_SET_FEATURES_SUPPRESSED: 'map:setfeaturessuppressed',
150
152
  /** @internal Set the active feature in the accessible features list. Payload: { id: string | null } */
151
153
  MAP_SET_ACTIVE_FEATURE: 'map:setactivefeature',
152
154
  /** @internal Select the active listbox feature as the real selection (Enter key). Payload: none */
@@ -13,5 +13,12 @@ export const mergeConfig = (userConfig = {}) => {
13
13
  config.mapViewQueryParam = mapViewParamKey
14
14
  }
15
15
 
16
+ // mapOnly has no launcher button or history entry to exit back to, so an exit
17
+ // button never makes sense there regardless of hasExitButton.
18
+ if (config.behaviour === 'mapOnly' && config.hasExitButton) {
19
+ console.warn('[InteractiveMap] hasExitButton has no effect when behaviour is \'mapOnly\' — there is nothing to exit to.')
20
+ config.hasExitButton = false
21
+ }
22
+
16
23
  return config
17
24
  }
@@ -40,4 +40,24 @@ describe('mergeConfig', () => {
40
40
  expect(warnSpy).not.toHaveBeenCalled()
41
41
  warnSpy.mockRestore()
42
42
  })
43
+
44
+ it('sanitises hasExitButton to false for mapOnly behaviour', () => {
45
+ const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {})
46
+ const result = mergeConfig({ behaviour: 'mapOnly', hasExitButton: true })
47
+ expect(result.hasExitButton).toBe(false)
48
+ expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining("hasExitButton has no effect when behaviour is 'mapOnly'"))
49
+ warnSpy.mockRestore()
50
+ })
51
+
52
+ it('leaves hasExitButton alone for non-mapOnly behaviours', () => {
53
+ const result = mergeConfig({ behaviour: 'buttonFirst', hasExitButton: true })
54
+ expect(result.hasExitButton).toBe(true)
55
+ })
56
+
57
+ it('does not warn when hasExitButton is already false for mapOnly', () => {
58
+ const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {})
59
+ mergeConfig({ behaviour: 'mapOnly', hasExitButton: false })
60
+ expect(warnSpy).not.toHaveBeenCalled()
61
+ warnSpy.mockRestore()
62
+ })
43
63
  })
@@ -31,7 +31,7 @@
31
31
  @use '../App/components/Markers/Markers.module';
32
32
  @use '../App/components/Viewport/Features.module';
33
33
  @use '../App/components/Actions/Actions.module';
34
- @use '../App/components/MoveControl/MoveControl.module';
34
+ @use '../App/components/MoveControls/MoveControls.module';
35
35
 
36
36
  // Components that dont have a corresponding React Component
37
37
  @use 'components';
@@ -26,6 +26,7 @@
26
26
  // Tooltips
27
27
  --tooltip-background-color: #383F43;
28
28
  --tooltip-foreground-color: #ffffff;
29
+ --tooltip-hover-color: #505a5f;
29
30
 
30
31
  // Modals
31
32
  --modal-background-color: #0b0c0c;
@@ -39,9 +39,8 @@
39
39
  --panel-close-button-gap: 4px;
40
40
  --panel-heading-margin-top: 12px;
41
41
  --panel-margin: 15px;
42
- --banner-close-button-gap: 0px;
43
- --banner-max-desktop-width: 400px;
44
- --banner-collapse-margin: 14px;
42
+ --banner-preferred-width: 280px; // Docked max-width, and the gutter threshold JS docks/stacks against
43
+ --banner-border-radius: 0px; // Styled like a hint, not a panel
45
44
 
46
45
  // Popup menu
47
46
  --popup-menu-min-width: 200px;
@@ -1,3 +1,3 @@
1
1
  :root {
2
- --duration: 0.2s;
2
+ --duration: 0s;
3
3
  }
@@ -108,6 +108,50 @@ class EventBus {
108
108
  return this.emit(eventName, ...args)
109
109
  }
110
110
 
111
+ /**
112
+ * Like `emit`, but also registers a listener for the corresponding `Required` event.
113
+ *
114
+ * Use this for events that may be requested before or after the emitter side is ready
115
+ * e.g. called from plugins that require a state reference from a different plugin like this:
116
+ * const removeRegistryListener = eventBus.emitWhenRequested('datasets:registry', datasetRegistry)
117
+ *
118
+ * @param {string} eventName
119
+ * @param {...*} args
120
+ * @returns {Function} A function to remove the listener for the `Required` event.
121
+ */
122
+ emitWhenRequested (eventName, ...args) {
123
+ const eventRequestedName = `${eventName}Requested`
124
+ const eventReadyName = `${eventName}Ready`
125
+ const handleOnRequired = () => this.emit(eventReadyName, ...args)
126
+ // Add a listener that will emit the event whenever requested
127
+ this.on(eventRequestedName, handleOnRequired)
128
+ // Also emit the event immediately, in case a listener is already waiting for it
129
+ handleOnRequired()
130
+ return () => this.off(eventRequestedName, handleOnRequired)
131
+ }
132
+
133
+ /**
134
+ * Like `emit`, but appends `Requested` to the event.
135
+ * used for events that require a response from another plugin,
136
+ * e.g. `datasets:registryRequested` will be emitted by the menu plugin,
137
+ * via `eventBus.requestOnce('datasets:registry')`, and the datasets plugin will respond with `datasets:registryReady`.
138
+ * and the datasets plugin will respond with `datasets:registryReady`.
139
+ * via `eventBus.emitWhenRequested('datasets:registry', datasetRegistry)`.
140
+ *
141
+ * @param {string} eventName
142
+ * @param {Function} eventHandler
143
+ * @returns {this}
144
+ */
145
+ requestOnce (eventName, eventHandler) {
146
+ const eventRequestedName = `${eventName}Requested`
147
+ const eventReadyName = `${eventName}Ready`
148
+ // Note - must register the once listener before emitting the requested event,
149
+ // otherwise the event won't emit, as there are no listeners yet.
150
+ this.once(eventReadyName, eventHandler)
151
+ this.emit(eventRequestedName, eventName)
152
+ return this
153
+ }
154
+
111
155
  /**
112
156
  * Remove all handlers and clear any queued events.
113
157
  */
@@ -175,6 +175,89 @@ describe('emitWhenReady', () => {
175
175
  })
176
176
  })
177
177
 
178
+ describe('emitWhenRequested', () => {
179
+ let bus
180
+ beforeEach(() => { bus = createEventBus() })
181
+
182
+ it('immediately emits eventNameReady so an already-waiting listener receives the args', () => {
183
+ const handler = jest.fn()
184
+ bus.on('datasets:registryReady', handler)
185
+ bus.emitWhenRequested('datasets:registry', 'registryValue')
186
+ expect(handler).toHaveBeenCalledWith('registryValue')
187
+ })
188
+
189
+ it('emits eventNameReady with args whenever eventNameRequested fires after registration', () => {
190
+ const handler = jest.fn()
191
+ bus.on('datasets:registryReady', handler)
192
+ bus.emitWhenRequested('datasets:registry', 'registryValue')
193
+ handler.mockClear()
194
+ bus.emit('datasets:registryRequested')
195
+ expect(handler).toHaveBeenCalledWith('registryValue')
196
+ })
197
+
198
+ it('forwards multiple args to the Ready event', () => {
199
+ const handler = jest.fn()
200
+ bus.on('datasets:registryReady', handler)
201
+ bus.emitWhenRequested('datasets:registry', 'a', 'b')
202
+ expect(handler).toHaveBeenCalledWith('a', 'b')
203
+ })
204
+
205
+ it('returns a cleanup function that stops responding to future Requested events', () => {
206
+ const handler = jest.fn()
207
+ bus.on('datasets:registryReady', handler)
208
+ const remove = bus.emitWhenRequested('datasets:registry', 'registryValue')
209
+ handler.mockClear()
210
+ remove()
211
+ bus.emit('datasets:registryRequested')
212
+ expect(handler).not.toHaveBeenCalled()
213
+ })
214
+ })
215
+
216
+ describe('requestOnce', () => {
217
+ let bus
218
+ beforeEach(() => { bus = createEventBus() })
219
+
220
+ it('calls the handler when eventNameReady fires', () => {
221
+ const handler = jest.fn()
222
+ bus.requestOnce('datasets:registry', handler)
223
+ bus.emit('datasets:registryReady', 'registryValue')
224
+ expect(handler).toHaveBeenCalledWith('registryValue')
225
+ })
226
+
227
+ it('calls the handler only once even if eventNameReady fires multiple times', () => {
228
+ const handler = jest.fn()
229
+ bus.requestOnce('datasets:registry', handler)
230
+ bus.emit('datasets:registryReady', 'first')
231
+ bus.emit('datasets:registryReady', 'second')
232
+ expect(handler).toHaveBeenCalledTimes(1)
233
+ })
234
+
235
+ it('emits eventNameRequested so the provider side knows it is needed', () => {
236
+ const requestedHandler = jest.fn()
237
+ bus.on('datasets:registryRequested', requestedHandler)
238
+ bus.requestOnce('datasets:registry', jest.fn())
239
+ expect(requestedHandler).toHaveBeenCalled()
240
+ })
241
+
242
+ it('returns this for chaining', () => {
243
+ expect(bus.requestOnce('datasets:registry', jest.fn())).toBe(bus)
244
+ })
245
+
246
+ it('works with emitWhenRequested when requestOnce is called first', () => {
247
+ const handler = jest.fn()
248
+ bus.requestOnce('datasets:registry', handler)
249
+ bus.emitWhenRequested('datasets:registry', 'registryValue')
250
+ expect(handler).toHaveBeenCalledWith('registryValue')
251
+ })
252
+
253
+ it('works with emitWhenRequested when emitWhenRequested is called first', () => {
254
+ const handler = jest.fn()
255
+ bus.emitWhenRequested('datasets:registry', 'registryValue')
256
+ bus.requestOnce('datasets:registry', handler)
257
+ expect(handler).toHaveBeenCalledWith('registryValue')
258
+ })
259
+ })
260
+
178
261
  describe('createEventBus factory', () => {
179
262
  /**
180
263
  * Test to ensure coverage for the factory function (Line 50).
@@ -2,7 +2,7 @@ import { getValueForStyle } from '../utils/getValueForStyle.js'
2
2
  import { symbolDefaults, pin, circle, square, graphics } from '../config/symbolConfig.js'
3
3
  import { getSymbolStyleColors, getSymbolViewBox } from '../utils/symbolUtils.js'
4
4
  import { THEME_COLORS } from '../config/mapTheme.js'
5
- import { rasteriseToImageData } from '../../providers/maplibre/src/utils/rasteriseToImageData.js'
5
+ import { rasteriseToImageData } from '../utils/rasteriseToImageData.js'
6
6
 
7
7
  const symbols = new Map()
8
8
  // Module-level cache: imageId → ImageData. Avoids re-rasterising identical symbols.
package/src/test-utils.js CHANGED
@@ -32,6 +32,11 @@ export const createMockRegistries = (overrides = {}) => {
32
32
  registeredPlugins: [],
33
33
  registerPlugin: jest.fn(),
34
34
  clear: jest.fn()
35
+ },
36
+ keyboardShortcutRegistry: {
37
+ registerKeyboardShortcut: jest.fn(),
38
+ setProviderSupportedShortcuts: jest.fn(),
39
+ getKeyboardShortcuts: jest.fn(() => [])
35
40
  }
36
41
  }
37
42
  }
package/src/types.js CHANGED
@@ -28,8 +28,18 @@
28
28
  *
29
29
  * @typedef {Object} ControlBreakpointConfig
30
30
  *
31
+ * @property {number} [order]
32
+ * The order the control appears within its slot (or, when targeting a panel, within that
33
+ * panel's body — see `slot` below).
34
+ *
31
35
  * @property {string} slot
32
- * Slot identifier.
36
+ * Slot identifier. In addition to the standard layout slots, a control may target a panel's
37
+ * body directly by setting this to `'<panelId>-panel'` (the panel id in kebab-case, suffixed
38
+ * with `-panel` — mirrors the `'<buttonId>-button'` convention panels use to render next to a
39
+ * specific button). Any plugin may target any panel this way, including one registered by a
40
+ * different plugin. The panel's own content and every control targeting it are ordered together
41
+ * via `order`. Only supported by panels with a `render` component — a panel using static `html`
42
+ * can't host injected controls, since `dangerouslySetInnerHTML` owns its body's children.
33
43
  */
34
44
 
35
45
  /**
@@ -697,8 +707,8 @@
697
707
  * @property {boolean} [enableFullscreen=false]
698
708
  * Whether a toggle fullscreen button is displayed.
699
709
  *
700
- * @property {boolean} [enableMoveControl=true]
701
- * Whether the move control is displayed — a button that reveals directional pan,
710
+ * @property {boolean} [enableMoveControls=true]
711
+ * Whether the move controls are displayed — a button that reveals directional pan,
702
712
  * zoom, and step-size buttons, providing a non-dragging alternative to panning
703
713
  * and zooming the map (WCAG 2.5.7). Unlike enableZoomControls, it remains visible
704
714
  * when the interface type is 'touch'. When enabled, enableZoomControls' buttons
@@ -706,7 +716,7 @@
706
716
  *
707
717
  * @property {boolean} [enableZoomControls=true]
708
718
  * Whether zoom control buttons are displayed. Not displayed when the interface
709
- * type is 'touch', or when enableMoveControl is enabled.
719
+ * type is 'touch', or when enableMoveControls is enabled.
710
720
  *
711
721
  * @property {[number, number, number, number]} [extent]
712
722
  * Initial extent [minX, minY, maxX, maxY]. Equivalent to bounds; use whichever matches your map provider's terminology.
@@ -722,16 +732,24 @@
722
732
  * In `mapOnly` behaviour the Back button is hidden when there is no browser history to go back to.
723
733
  *
724
734
  * @property {boolean} [hasExitButton=false]
725
- * Whether an exit map button is displayed when the app is fullscreen.
735
+ * Whether an exit map button is displayed. Only shown when the behaviour is `buttonFirst`
736
+ * or `hybrid` and the map is fullscreen - `mapOnly` has no launcher button or history entry
737
+ * to exit back to, so the exit button is never shown there.
726
738
  *
727
739
  * @property {number | null} [hybridWidth]
728
740
  * Optional breakpoint (in pixels) for hybrid behaviour. Defaults to 'maxMobileWidth' when not set.
729
741
  *
730
742
  * @property {string} [keyboardHintText]
731
- * HTML string providing keyboard shortcut instructions for accessibility users.
743
+ * HTML string providing keyboard shortcut instructions for accessibility users, announced via aria-describedby whenever the map viewport gains focus.
744
+ *
745
+ * @property {string} [mapHintText]
746
+ * Visually hidden text, rendered immediately before the map for screen reader users, explaining that it must be focused before keyboard commands work. Prefixed with mapLabel, so multiple maps on one page can be told apart.
732
747
  *
733
748
  * @property {string} [mapLabel='Interactive map']
734
- * Accessible label for the map, announced by screen readers.
749
+ * Accessible label for the map, announced by screen readers. Also prefixed onto mapHintText, so give each map on a page a distinct label.
750
+ *
751
+ * @property {string} [moveControlsHintText]
752
+ * Visually hidden text describing the move controls button, appended to keyboardHintText when enableMoveControls is true.
735
753
  *
736
754
  * @property {MapProviderDescriptor} [mapProvider]
737
755
  * A factory function that returns a map provider instance (e.g. maplibreProvider()).
package/webpack.umd.mjs CHANGED
@@ -145,6 +145,8 @@ const ALL_BUILDS = [
145
145
  { entryPath: './plugins/search/src/index.js', libraryPath: 'searchPlugin', outDir: 'plugins/search/dist/umd' },
146
146
  { entryPath: './plugins/interact/src/index.js', libraryPath: 'interactPlugin', outDir: 'plugins/interact/dist/umd' },
147
147
  { entryPath: './plugins/datasets/src/index.js', libraryPath: 'datasetsPlugin', outDir: 'plugins/datasets/dist/umd', cssOutDir: 'plugins/datasets/dist' },
148
+ { entryPath: './plugins/map-key/src/index.js', libraryPath: 'mapKeyPlugin', outDir: 'plugins/map-key/dist/umd', cssOutDir: 'plugins/map-key/dist' },
149
+ { entryPath: './plugins/menu/src/index.js', libraryPath: 'menuPlugin', outDir: 'plugins/menu/dist/umd', cssOutDir: 'plugins/menu/dist' },
148
150
  { entryPath: './plugins/beta/map-styles/src/index.js', libraryPath: 'mapStylesPlugin', outDir: 'plugins/beta/map-styles/dist/umd' },
149
151
  { entryPath: './plugins/draw/src/index.js', libraryPath: 'drawPlugin', outDir: 'plugins/draw/dist/umd' },
150
152
  { entryPath: './plugins/beta/draw-ml/src/index.js', libraryPath: 'drawMLPlugin', outDir: 'plugins/beta/draw-ml/dist/umd' },
@@ -1,7 +0,0 @@
1
- export const EmptyKey = ({ text }) => {
2
- return (
3
- <div className='im-c-datasets-key'>
4
- <p className='im-c-datasets-key__empty-message'>{text}</p>
5
- </div>
6
- )
7
- }
@@ -1,50 +0,0 @@
1
- import React from 'react'
2
- import { EmptyKey } from './EmptyKey.jsx'
3
- import { KeyItem } from './KeyItem.jsx'
4
- import { KeyGroupItem } from './KeyGroupItem.jsx'
5
- import { datasetRegistry } from '../../registry/datasetRegistry.js'
6
-
7
- export const Key = ({
8
- pluginConfig: { noKeyItemText },
9
- mapState: { mapStyle },
10
- services: { symbolRegistry, patternRegistry }
11
- }) => {
12
- const { items: keyGroups, hasGroups } = datasetRegistry.keyItems()
13
-
14
- if (!keyGroups?.length) {
15
- return (<EmptyKey text={noKeyItemText} />)
16
- }
17
-
18
- const containerClass = `im-c-datasets-key${hasGroups ? ' im-c-datasets-key--has-groups' : ''}`
19
- return (
20
- <div className={containerClass}>{keyGroups.map(item => {
21
- const key = item.type === 'group' ? item.groupLabel.toLowerCase().replaceAll(/\s+/g, '-') : item.dataset.id
22
-
23
- if (item.type === 'sublayers' || item.type === 'group') {
24
- const datasets = item.type === 'sublayers' ? item.sublayers : item.datasets
25
- const label = item.type === 'sublayers' ? item.dataset.label : item.groupLabel
26
- return (
27
- <KeyGroupItem
28
- key={key}
29
- headingId={`key-heading-${key}`}
30
- label={label}
31
- datasets={datasets}
32
- symbolRegistry={symbolRegistry}
33
- patternRegistry={patternRegistry}
34
- mapStyle={mapStyle}
35
- />
36
- )
37
- }
38
- return (
39
- <KeyItem
40
- key={key}
41
- registryDataset={item.dataset}
42
- symbolRegistry={symbolRegistry}
43
- patternRegistry={patternRegistry}
44
- mapStyle={mapStyle}
45
- />
46
- )
47
- })}
48
- </div>
49
- )
50
- }
@@ -1,18 +0,0 @@
1
- import { KeyItem } from './KeyItem.jsx'
2
-
3
- export const KeyGroupItem = ({ headingId, label, datasets, symbolRegistry, patternRegistry, mapStyle }) => {
4
- return (
5
- <section className='im-c-datasets-key__group' aria-labelledby={headingId}>
6
- <h3 id={headingId} className='im-c-datasets-key__group-heading'>{label}</h3>
7
- {datasets.map(dataset =>
8
- <KeyItem
9
- key={`${dataset.id}`}
10
- registryDataset={dataset}
11
- symbolRegistry={symbolRegistry}
12
- patternRegistry={patternRegistry}
13
- mapStyle={mapStyle}
14
- />
15
- )}
16
- </section>
17
- )
18
- }
@@ -1,23 +0,0 @@
1
- import { getValueForStyle } from '../../../../../src/utils/getValueForStyle.js'
2
- import { KeySvg } from './KeySvg.jsx'
3
-
4
- export const KeyItem = ({ registryDataset, symbolRegistry, patternRegistry, mapStyle }) => {
5
- if (!registryDataset.showInKey) {
6
- return null
7
- }
8
- return (
9
- <dl className='im-c-datasets-key__item'>
10
- <dt className='im-c-datasets-key__item-symbol'>
11
- <KeySvg registryDataset={registryDataset} symbolRegistry={symbolRegistry} patternRegistry={patternRegistry} mapStyle={mapStyle} />
12
- </dt>
13
- <dd className='im-c-datasets-key__item-label'>
14
- {registryDataset.label}
15
- {registryDataset.symbolDescription && (
16
- <span className='govuk-visually-hidden'>
17
- ({getValueForStyle(registryDataset.symbolDescription, mapStyle.id)})
18
- </span>
19
- )}
20
- </dd>
21
- </dl>
22
- )
23
- }
@@ -1,22 +0,0 @@
1
- import { KeySvgPattern } from './KeySvgPattern.jsx'
2
- import { KeySvgSymbol } from './KeySvgSymbol.jsx'
3
- import { KeySvgLine } from './KeySvgLine.jsx'
4
- import { KeySvgRect } from './KeySvgRect.jsx'
5
-
6
- export const KeySvg = ({ symbolRegistry, registryDataset, mapStyle, patternRegistry }) => {
7
- const { hasSymbol, hasPattern, style } = registryDataset
8
- const symbolDef = hasSymbol && symbolRegistry.getSymbolDef(style)
9
- if (symbolDef) {
10
- return <KeySvgSymbol mapStyle={mapStyle} registryDataset={registryDataset} symbolRegistry={symbolRegistry} symbolDef={symbolDef} />
11
- }
12
-
13
- if (hasPattern) {
14
- return <KeySvgPattern mapStyle={mapStyle} registryDataset={registryDataset} patternRegistry={patternRegistry} />
15
- }
16
-
17
- if (style.keySymbolShape === 'line') {
18
- return <KeySvgLine mapStyle={mapStyle} registryDataset={registryDataset} />
19
- }
20
-
21
- return <KeySvgRect mapStyle={mapStyle} registryDataset={registryDataset} />
22
- }
@@ -1,19 +0,0 @@
1
- import { svgProps, SVG_SIZE, SVG_CENTER } from './svgProperties.js'
2
- import { getValueForStyle } from '../../../../../src/utils/getValueForStyle.js'
3
-
4
- export const KeySvgLine = ({ mapStyle, registryDataset }) => {
5
- const { style } = registryDataset
6
- return (
7
- <svg {...svgProps}>
8
- <line
9
- x1={style.strokeWidth / 2}
10
- y1={SVG_CENTER}
11
- x2={SVG_SIZE - style.strokeWidth / 2}
12
- y2={SVG_CENTER}
13
- stroke={getValueForStyle(style.stroke, mapStyle.id)}
14
- strokeWidth={style.strokeWidth}
15
- strokeLinecap='round'
16
- />
17
- </svg>
18
- )
19
- }
@@ -1,13 +0,0 @@
1
- import { svgProps } from './svgProperties.js'
2
- const PATTERN_INSET = 2
3
-
4
- export const KeySvgPattern = ({ patternRegistry, registryDataset, mapStyle }) => {
5
- const { style } = registryDataset
6
- const paths = patternRegistry.getKeyPatternPaths(style, mapStyle.id)
7
- return (
8
- <svg {...svgProps}>
9
- <g dangerouslySetInnerHTML={{ __html: paths.border }} />
10
- <g transform={`translate(${PATTERN_INSET}, ${PATTERN_INSET})`} dangerouslySetInnerHTML={{ __html: paths.content }} />
11
- </svg>
12
- )
13
- }
@@ -1,22 +0,0 @@
1
- import { getValueForStyle } from '../../../../../src/utils/getValueForStyle.js'
2
- import { svgProps, SVG_SIZE } from './svgProperties.js'
3
-
4
- export const KeySvgRect = ({ mapStyle, registryDataset }) => {
5
- const { style } = registryDataset
6
- return (
7
- <svg {...svgProps}>
8
- <rect
9
- x={style.strokeWidth / 2}
10
- y={style.strokeWidth / 2}
11
- width={SVG_SIZE - style.strokeWidth}
12
- height={SVG_SIZE - style.strokeWidth}
13
- rx={style.strokeWidth}
14
- ry={style.strokeWidth}
15
- fill={getValueForStyle(style.fill, mapStyle.id)}
16
- stroke={getValueForStyle(style.stroke, mapStyle.id)}
17
- strokeWidth={style.strokeWidth}
18
- strokeLinejoin='round'
19
- />
20
- </svg>
21
- )
22
- }
@@ -1,16 +0,0 @@
1
- import { getSymbolStyleColors, getSymbolViewBox } from '../../../../../src/utils/symbolUtils.js'
2
- import { svgSymbolProps } from './svgProperties.js'
3
-
4
- export const KeySvgSymbol = ({ symbolRegistry, registryDataset, mapStyle, symbolDef }) => {
5
- const { style } = registryDataset
6
- const mapColorScheme = mapStyle?.appColorScheme ?? 'light'
7
- const keyMapStyle = { ...mapStyle, mapColorScheme }
8
-
9
- const resolvedSvg = symbolRegistry.resolve(symbolDef, getSymbolStyleColors(style), keyMapStyle)
10
- const viewBox = getSymbolViewBox(style, symbolDef)
11
- return (
12
- <svg {...svgSymbolProps} viewBox={viewBox}>
13
- <g dangerouslySetInnerHTML={{ __html: resolvedSvg }} />
14
- </svg>
15
- )
16
- }
@@ -1,41 +0,0 @@
1
- import React from 'react'
2
- import { isVisibleWhen } from '../../registry/isVisibleWhen.js'
3
- import { LayersMenuRadio } from './LayersMenuRadio.jsx'
4
-
5
- export const LayersRadioGroupWrapper = ({ pluginState, menuGroup }) => {
6
- const { id, items, visibleWhen } = menuGroup
7
- const visible = visibleWhen ? isVisibleWhen(visibleWhen) : true
8
- if (!visible) {
9
- return null
10
- }
11
-
12
- const { menuState, dispatch } = pluginState
13
- const value = menuState[id]
14
- const handleChange = (event) => {
15
- dispatch({ type: 'UPDATE_MENU_STATE', payload: { [id]: event.target.value } })
16
- }
17
-
18
- const wrapperClass = 'govuk-form-group im-c-datasets-layers-group'
19
- return (
20
- <div key={menuGroup.id} className={wrapperClass}>
21
- <fieldset className='im-c-datasets-layers-group__fieldset'>
22
- <legend className='im-c-datasets-layers-group__legend'>
23
- <h3>
24
- {menuGroup.label}
25
- </h3>
26
- </legend>
27
- <div className='govuk-radios govuk-radios--small' data-module='govuk-radios'>
28
- {items.map((menuGroupItem) =>
29
- <LayersMenuRadio
30
- key={menuGroupItem.id}
31
- menuGroupItem={menuGroupItem}
32
- name={id}
33
- checked={menuGroupItem.id === value}
34
- onChange={handleChange}
35
- />
36
- )}
37
- </div>
38
- </fieldset>
39
- </div>
40
- )
41
- }