@defra/interactive-map 0.0.30-alpha → 0.0.32-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 (247) hide show
  1. package/README.md +2 -2
  2. package/assets/images/bright-ofm-thumb.jpg +0 -0
  3. package/assets/images/dark-ofm-thumb.jpg +0 -0
  4. package/assets/images/road-ofm-thumb.jpg +0 -0
  5. package/assets/templates/add-polygons.njk +143 -0
  6. package/assets/templates/add-symbols.njk +119 -0
  7. package/assets/templates/{map.njk → basic-map.njk} +9 -17
  8. package/assets/templates/button-map.njk +56 -0
  9. package/assets/templates/draw-tools.njk +161 -0
  10. package/assets/templates/marker-panel.njk +91 -0
  11. package/assets/templates/place-marker.njk +104 -0
  12. package/assets/templates/search-control.njk +98 -0
  13. package/assets/templates/select-feature.njk +101 -0
  14. package/assets/templates/style-switcher.njk +87 -0
  15. package/assets/templates/toggle-marker-label.njk +74 -0
  16. package/dist/css/index.css +1 -1
  17. package/dist/esm/im-core.js +1 -1
  18. package/dist/esm/im-shell.js +1 -1
  19. package/dist/umd/im-core.js +1 -1
  20. package/dist/umd/index.js +1 -1
  21. package/docs/api/context.md +4 -4
  22. package/docs/api.md +166 -37
  23. package/docs/assets/css/docusaurus.scss +36 -4
  24. package/docs/assets/images/add-polygons.jpg +0 -0
  25. package/docs/assets/images/add-symbols.jpg +0 -0
  26. package/docs/assets/images/basic-map.jpg +0 -0
  27. package/docs/assets/images/button-first.jpg +0 -0
  28. package/docs/assets/images/deuteranopia-ozs-map-thumb.jpg +0 -0
  29. package/docs/assets/images/draw.jpg +0 -0
  30. package/docs/assets/images/marker-panel.jpg +0 -0
  31. package/docs/assets/images/night-ozs-map-thumb.jpg +0 -0
  32. package/docs/assets/images/outdoor-ozs-map-thumb.jpg +0 -0
  33. package/docs/assets/images/place-marker.jpg +0 -0
  34. package/docs/assets/images/screenshot.jpg +0 -0
  35. package/docs/assets/images/search.jpg +0 -0
  36. package/docs/assets/images/select-feature.jpg +0 -0
  37. package/docs/assets/images/style-switcher.jpg +0 -0
  38. package/docs/assets/images/toggle-marker-label.jpg +0 -0
  39. package/docs/assets/images/tritanopia-ozs-map-thumb.jpg +0 -0
  40. package/docs/examples/add-marker-with-panel.mdx +3 -3
  41. package/docs/examples/add-polygons.mdx +225 -0
  42. package/docs/examples/add-symbols.mdx +177 -0
  43. package/docs/examples/basic-map.mdx +2 -2
  44. package/docs/examples/draw-tools.mdx +271 -0
  45. package/docs/examples/index.mdx +95 -11
  46. package/docs/examples/place-marker.mdx +151 -0
  47. package/docs/examples/search-control.mdx +71 -0
  48. package/docs/examples/select-feature.mdx +146 -0
  49. package/docs/examples/style-switcher.mdx +135 -0
  50. package/docs/examples/toggle-marker-label.mdx +3 -3
  51. package/docs/plugins/datasets.md +157 -122
  52. package/docs/plugins/interact.md +1 -4
  53. package/docusaurus.config.cjs +9 -2
  54. package/govuk-prototype-kit.config.json +52 -2
  55. package/package.json +1 -1
  56. package/plugins/beta/datasets/dist/css/index.css +5 -2
  57. package/plugins/beta/datasets/dist/esm/im-datasets-ml-adapter.js +1 -0
  58. package/plugins/beta/datasets/dist/esm/im-datasets-plugin.js +1 -1
  59. package/plugins/beta/datasets/dist/esm/index.js +1 -1
  60. package/plugins/beta/datasets/dist/umd/im-datasets-ml-adapter.js +2 -0
  61. package/plugins/beta/datasets/dist/umd/im-datasets-plugin.js +2 -0
  62. package/plugins/beta/datasets/dist/umd/index.js +2 -0
  63. package/plugins/beta/datasets/src/adapters/loadLayerAdapter.js +33 -0
  64. package/plugins/beta/datasets/src/adapters/maplibre/layerBuilders.js +44 -120
  65. package/plugins/beta/datasets/src/adapters/maplibre/maplibreLayerAdapter.js +145 -245
  66. package/plugins/beta/datasets/src/adapters/maplibre/maplibreLayerAdapter.test.js +516 -0
  67. package/plugins/beta/datasets/src/adapters/maplibre/registry/mapLibreDataset.js +209 -0
  68. package/plugins/beta/datasets/src/adapters/maplibre/registry/mapLibreDataset.test.js +483 -0
  69. package/plugins/beta/datasets/src/api/addDataset.js +2 -5
  70. package/plugins/beta/datasets/src/api/addDataset.test.js +16 -0
  71. package/plugins/beta/datasets/src/api/getOpacity.js +14 -14
  72. package/plugins/beta/datasets/src/api/getOpacity.test.js +72 -0
  73. package/plugins/beta/datasets/src/api/getStyle.js +8 -9
  74. package/plugins/beta/datasets/src/api/getStyle.test.js +42 -0
  75. package/plugins/beta/datasets/src/api/removeDataset.js +7 -7
  76. package/plugins/beta/datasets/src/api/removeDataset.test.js +45 -0
  77. package/plugins/beta/datasets/src/api/setData.js +9 -3
  78. package/plugins/beta/datasets/src/api/setData.test.js +62 -0
  79. package/plugins/beta/datasets/src/api/setDatasetVisibility.js +5 -30
  80. package/plugins/beta/datasets/src/api/setDatasetVisibility.test.js +31 -0
  81. package/plugins/beta/datasets/src/api/setFeatureVisibility.js +9 -18
  82. package/plugins/beta/datasets/src/api/setFeatureVisibility.test.js +74 -0
  83. package/plugins/beta/datasets/src/api/setGlobals.js +20 -0
  84. package/plugins/beta/datasets/src/api/setGlobals.test.js +63 -0
  85. package/plugins/beta/datasets/src/api/setOpacity.js +8 -27
  86. package/plugins/beta/datasets/src/api/setOpacity.test.js +31 -0
  87. package/plugins/beta/datasets/src/api/setStyle.js +5 -21
  88. package/plugins/beta/datasets/src/api/setStyle.test.js +53 -0
  89. package/plugins/beta/datasets/src/components/Key/Key.jsx +51 -0
  90. package/plugins/beta/datasets/src/components/Key/KeyGroupItem.jsx +18 -0
  91. package/plugins/beta/datasets/src/components/Key/KeyItem.jsx +20 -0
  92. package/plugins/beta/datasets/src/components/Key/KeySvg.jsx +22 -0
  93. package/plugins/beta/datasets/src/components/Key/KeySvg.test.jsx +87 -0
  94. package/plugins/beta/datasets/src/components/Key/KeySvgLine.jsx +19 -0
  95. package/plugins/beta/datasets/src/components/Key/KeySvgLine.test.jsx +71 -0
  96. package/plugins/beta/datasets/src/components/{KeySvgPattern.jsx → Key/KeySvgPattern.jsx} +3 -4
  97. package/plugins/beta/datasets/src/components/Key/KeySvgPattern.test.jsx +55 -0
  98. package/plugins/beta/datasets/src/components/Key/KeySvgRect.jsx +22 -0
  99. package/plugins/beta/datasets/src/components/Key/KeySvgRect.test.jsx +85 -0
  100. package/plugins/beta/datasets/src/components/{KeySvgSymbol.jsx → Key/KeySvgSymbol.jsx} +5 -5
  101. package/plugins/beta/datasets/src/components/Key/KeySvgSymbol.test.jsx +80 -0
  102. package/plugins/beta/datasets/src/components/Key/svgProperties.test.js +61 -0
  103. package/plugins/beta/datasets/src/{panels → components/LayersMenu}/Layers.module.scss +15 -11
  104. package/plugins/beta/datasets/src/components/LayersMenu/LayersMenu.jsx +33 -0
  105. package/plugins/beta/datasets/src/components/LayersMenu/LayersMenuCheckbox.jsx +31 -0
  106. package/plugins/beta/datasets/src/components/LayersMenu/LayersMenuGroupWrapper.jsx +19 -0
  107. package/plugins/beta/datasets/src/datasets.scss +2 -2
  108. package/plugins/beta/datasets/src/fetch/createDynamicSource.js +8 -8
  109. package/plugins/beta/datasets/src/{DatasetsInit.jsx → initialise/DatasetsInit.jsx} +19 -21
  110. package/plugins/beta/datasets/src/{defaults.js → initialise/defaults.js} +17 -2
  111. package/plugins/beta/datasets/src/initialise/defaults.test.js +127 -0
  112. package/plugins/beta/datasets/src/{datasets.js → initialise/initialiseDatasets.js} +30 -26
  113. package/plugins/beta/datasets/src/initialise/initialiseDatasets.test.js +273 -0
  114. package/plugins/beta/datasets/src/manifest.js +8 -6
  115. package/plugins/beta/datasets/src/reducers/__data__/demoDatasets.js +253 -0
  116. package/plugins/beta/datasets/src/reducers/datasetsToMenu.js +83 -0
  117. package/plugins/beta/datasets/src/reducers/datasetsToMenu.test.js +84 -0
  118. package/plugins/beta/datasets/src/reducers/mappedDatasetsReducer.js +41 -0
  119. package/plugins/beta/datasets/src/reducers/mappedDatasetsReducer.test.js +117 -0
  120. package/plugins/beta/datasets/src/reducers/pluginState.js +206 -0
  121. package/plugins/beta/datasets/src/reducers/pluginState.test.js +386 -0
  122. package/plugins/beta/datasets/src/registry/__mocks__/datasetRegistry.js +29 -0
  123. package/plugins/beta/datasets/src/registry/createDataset.js +5 -0
  124. package/plugins/beta/datasets/src/registry/dataset.js +176 -0
  125. package/plugins/beta/datasets/src/registry/dataset.test.js +497 -0
  126. package/plugins/beta/datasets/src/registry/datasetDefinitionCache.js +35 -0
  127. package/plugins/beta/datasets/src/registry/datasetRegistry.js +116 -0
  128. package/plugins/beta/datasets/src/registry/datasetRegistry.test.js +335 -0
  129. package/plugins/beta/datasets/src/registry/dynamicGeoJson.js +17 -0
  130. package/plugins/beta/datasets/src/registry/globalDataset.js +36 -0
  131. package/plugins/beta/draw-es/dist/esm/im-draw-es-plugin.js +1 -1
  132. package/plugins/beta/draw-es/src/api/addFeature.js +12 -3
  133. package/plugins/beta/draw-es/src/events.js +8 -3
  134. package/plugins/beta/draw-es/src/events.test.js +2 -0
  135. package/plugins/beta/draw-es/src/graphic.js +26 -2
  136. package/plugins/beta/draw-ml/dist/esm/im-draw-ml-plugin.js +1 -1
  137. package/plugins/beta/draw-ml/dist/umd/im-draw-ml-plugin.js +1 -1
  138. package/plugins/beta/draw-ml/src/DrawInit.jsx +8 -0
  139. package/plugins/beta/draw-ml/src/api/newLine.js +1 -0
  140. package/plugins/beta/draw-ml/src/api/newPolygon.js +1 -0
  141. package/plugins/beta/draw-ml/src/events.js +13 -1
  142. package/plugins/beta/draw-ml/src/index.js +1 -1
  143. package/plugins/beta/draw-ml/src/manifest.js +3 -0
  144. package/plugins/beta/draw-ml/src/modes/createDrawMode.js +21 -12
  145. package/plugins/beta/draw-ml/src/modes/editVertexMode.js +4 -0
  146. package/plugins/beta/draw-ol/dist/esm/EditMode.js +1 -1
  147. package/plugins/beta/draw-ol/dist/esm/im-draw-ol-plugin.js +1 -1
  148. package/plugins/beta/draw-ol/src/edit/keyboardHandler.js +4 -2
  149. package/plugins/beta/map-styles/src/mapStyles.scss +41 -41
  150. package/plugins/interact/dist/esm/im-interact-plugin.js +1 -1
  151. package/plugins/interact/dist/umd/im-interact-plugin.js +1 -1
  152. package/plugins/interact/dist/umd/index.js +1 -1
  153. package/plugins/interact/src/InteractInit.jsx +3 -5
  154. package/plugins/interact/src/InteractInit.test.js +1 -3
  155. package/plugins/interact/src/events.js +2 -29
  156. package/plugins/interact/src/events.test.js +4 -102
  157. package/plugins/interact/src/hooks/useAttachEvents.js +3 -4
  158. package/plugins/interact/src/hooks/useAttachEvents.test.js +1 -3
  159. package/plugins/interact/src/hooks/useCrossHairVisibility.js +4 -10
  160. package/plugins/interact/src/hooks/useCrossHairVisibility.test.js +5 -10
  161. package/plugins/interact/src/hooks/useHighlightSync.js +1 -10
  162. package/plugins/interact/src/hooks/useHighlightSync.test.js +2 -21
  163. package/plugins/interact/src/hooks/useInteractionHandlers.js +15 -12
  164. package/plugins/interact/src/hooks/useInteractionHandlers.test.js +28 -29
  165. package/plugins/interact/src/manifest.js +0 -35
  166. package/plugins/interact/src/manifest.test.js +3 -43
  167. package/plugins/interact/src/reducer.js +4 -22
  168. package/plugins/interact/src/reducer.test.js +11 -39
  169. package/plugins/search/dist/css/index.css +5 -2
  170. package/plugins/search/src/components/Form/Form.module.scss +5 -2
  171. package/plugins/search/src/search.scss +4 -4
  172. package/providers/beta/esri/dist/esm/im-esri-provider.js +1 -1
  173. package/providers/beta/esri/src/esriProvider.js +4 -0
  174. package/providers/beta/openlayers/dist/esm/im-openlayers-provider.js +1 -1
  175. package/providers/beta/openlayers/dist/umd/im-openlayers-provider.js +1 -1
  176. package/providers/beta/openlayers/src/openlayersProvider.js +4 -0
  177. package/providers/beta/openlayers/src/openlayersProvider.test.js +5 -0
  178. package/providers/maplibre/dist/esm/im-maplibre-provider.js +1 -1
  179. package/providers/maplibre/dist/umd/im-maplibre-provider.js +1 -1
  180. package/providers/maplibre/src/maplibreProvider.js +6 -4
  181. package/providers/maplibre/src/maplibreProvider.test.js +5 -0
  182. package/providers/maplibre/src/utils/highlightFeatures.js +74 -25
  183. package/providers/maplibre/src/utils/highlightFeatures.test.js +132 -0
  184. package/providers/maplibre/src/utils/patternImages.js +2 -4
  185. package/providers/maplibre/src/utils/symbolImages.js +1 -4
  186. package/rollup.esm.mjs +2 -8
  187. package/src/App/components/CrossHair/CrossHair.module.scss +8 -8
  188. package/src/App/components/MapButton/MapButton.jsx +16 -1
  189. package/src/App/components/MapButton/MapButton.module.scss +12 -1
  190. package/src/App/components/MapButton/MapButton.test.jsx +40 -1
  191. package/src/App/hooks/useContinueEnabledEvaluator.js +31 -0
  192. package/src/App/hooks/useContinueEnabledEvaluator.test.js +118 -0
  193. package/src/App/hooks/useEvaluateProp.js +15 -15
  194. package/src/App/hooks/useEvaluateProp.test.js +80 -76
  195. package/src/App/hooks/useLayoutMeasurements.js +11 -5
  196. package/src/App/hooks/useResizeObserver.js +15 -2
  197. package/src/App/hooks/useResizeObserver.test.js +1 -0
  198. package/src/App/renderer/PluginInits.jsx +2 -0
  199. package/src/App/renderer/mapButtons.js +21 -1
  200. package/src/App/renderer/mapButtons.test.js +46 -1
  201. package/src/App/store/appReducer.js +1 -1
  202. package/src/App/store/appReducer.test.js +37 -0
  203. package/src/InteractiveMap/InteractiveMap.js +14 -4
  204. package/src/InteractiveMap/InteractiveMap.test.js +11 -3
  205. package/src/InteractiveMap/behaviourController.js +3 -1
  206. package/src/InteractiveMap/behaviourController.test.js +6 -3
  207. package/src/InteractiveMap/domStateManager.js +2 -0
  208. package/src/config/appConfig.js +25 -0
  209. package/src/config/appConfig.test.js +50 -0
  210. package/src/config/defaults.js +1 -0
  211. package/src/config/events.js +21 -3
  212. package/src/scss/settings/_dimensions.scss +1 -0
  213. package/src/services/patternRegistry.js +8 -4
  214. package/src/types.js +7 -0
  215. package/src/utils/patternUtils.js +1 -2
  216. package/src/utils/patternUtils.test.js +9 -0
  217. package/webpack.dev.mjs +10 -0
  218. package/webpack.umd.mjs +1 -1
  219. package/docs/assets/images/screens-blue.jpg +0 -0
  220. package/docs/assets/images/screens-white.jpg +0 -0
  221. package/plugins/beta/datasets/dist/adapters/maplibre/esm/im-datasets-ml-adapter.js +0 -1
  222. package/plugins/beta/datasets/dist/adapters/maplibre/esm/index.js +0 -1
  223. package/plugins/beta/datasets/dist/umd/maplibre/im-datasets-maplibre-adapter.js +0 -2
  224. package/plugins/beta/datasets/dist/umd/maplibre/im-datasets-plugin.js +0 -2
  225. package/plugins/beta/datasets/dist/umd/maplibre/index.js +0 -2
  226. package/plugins/beta/datasets/src/adapters/maplibre/index.js +0 -18
  227. package/plugins/beta/datasets/src/adapters/maplibre/layerIds.js +0 -75
  228. package/plugins/beta/datasets/src/adapters/maplibre/patternImages.js +0 -27
  229. package/plugins/beta/datasets/src/adapters/maplibre/symbolImages.js +0 -31
  230. package/plugins/beta/datasets/src/components/KeySvg.jsx +0 -24
  231. package/plugins/beta/datasets/src/components/KeySvgLine.jsx +0 -19
  232. package/plugins/beta/datasets/src/components/KeySvgRect.jsx +0 -22
  233. package/plugins/beta/datasets/src/index.maplibre.umd.js +0 -23
  234. package/plugins/beta/datasets/src/panels/Key.jsx +0 -62
  235. package/plugins/beta/datasets/src/panels/Layers.jsx +0 -141
  236. package/plugins/beta/datasets/src/reducer.js +0 -219
  237. package/plugins/beta/datasets/src/reducers/keyReducer.js +0 -34
  238. package/plugins/beta/datasets/src/utils/filters.js +0 -34
  239. package/plugins/beta/datasets/src/utils/mergeSublayer.js +0 -86
  240. package/plugins/beta/draw-ml/dist/css/index.css +0 -21
  241. /package/plugins/beta/datasets/dist/umd/{maplibre/im-datasets-maplibre-adapter.js.LICENSE.txt → im-datasets-ml-adapter.js.LICENSE.txt} +0 -0
  242. /package/plugins/beta/datasets/dist/umd/{maplibre/im-datasets-plugin.js.LICENSE.txt → im-datasets-plugin.js.LICENSE.txt} +0 -0
  243. /package/plugins/beta/datasets/dist/umd/{maplibre/index.js.LICENSE.txt → index.js.LICENSE.txt} +0 -0
  244. /package/plugins/beta/datasets/src/components/{EmptyKey.jsx → Key/EmptyKey.jsx} +0 -0
  245. /package/plugins/beta/datasets/src/components/{EmptyKey.test.jsx → Key/EmptyKey.test.jsx} +0 -0
  246. /package/plugins/beta/datasets/src/{panels → components/Key}/Key.module.scss +0 -0
  247. /package/plugins/beta/datasets/src/components/{svgProperties.js → Key/svgProperties.js} +0 -0
@@ -1,75 +0,0 @@
1
- import { hasPattern } from '../../../../../../src/utils/patternUtils.js'
2
-
3
- // ─── Internal helpers ─────────────────────────────────────────────────────────
4
-
5
- const hasSymbol = (dataset) => !!dataset.symbol
6
-
7
- export const isDynamicSource = (dataset) =>
8
- typeof dataset.geojson === 'string' &&
9
- !!dataset.idProperty &&
10
- typeof dataset.transformRequest === 'function'
11
-
12
- const HASH_BASE = 36
13
- const MAX_TILE_ZOOM = 22
14
-
15
- export { MAX_TILE_ZOOM }
16
-
17
- export const hashString = (str) => {
18
- let hash = 0
19
- for (const ch of str) {
20
- hash = Math.trunc(((hash << 5) - hash) + ch.codePointAt(0))
21
- }
22
- return Math.abs(hash).toString(HASH_BASE)
23
- }
24
-
25
- // ─── Source ID ────────────────────────────────────────────────────────────────
26
-
27
- export const getSourceId = (dataset) => {
28
- if (dataset.tiles) {
29
- const tilesKey = Array.isArray(dataset.tiles) ? dataset.tiles.join(',') : dataset.tiles
30
- return `tiles-${hashString(tilesKey)}`
31
- }
32
- if (dataset.geojson) {
33
- if (isDynamicSource(dataset)) {
34
- return `geojson-dynamic-${dataset.id}`
35
- }
36
- if (typeof dataset.geojson === 'string') {
37
- return `geojson-${hashString(dataset.geojson)}`
38
- }
39
- return `geojson-${dataset.id}`
40
- }
41
- return `source-${dataset.id}`
42
- }
43
-
44
- // ─── Layer IDs ────────────────────────────────────────────────────────────────
45
-
46
- export const getLayerIds = (dataset) => {
47
- if (hasSymbol(dataset)) {
48
- return { fillLayerId: null, strokeLayerId: null, symbolLayerId: dataset.id }
49
- }
50
- const hasFill = (!!dataset.fill && dataset.fill !== 'transparent') || hasPattern(dataset)
51
- const hasStroke = !!dataset.stroke
52
- const fillLayerId = hasFill ? dataset.id : null
53
- let strokeLayerId = null
54
- if (hasStroke) {
55
- strokeLayerId = hasFill ? `${dataset.id}-stroke` : dataset.id
56
- }
57
- return { fillLayerId, strokeLayerId, symbolLayerId: null }
58
- }
59
-
60
- export const getSublayerLayerIds = (datasetId, sublayerId) => ({
61
- fillLayerId: `${datasetId}-${sublayerId}`,
62
- strokeLayerId: `${datasetId}-${sublayerId}-stroke`,
63
- symbolLayerId: `${datasetId}-${sublayerId}-symbol`
64
- })
65
-
66
- export const getAllLayerIds = (dataset) => {
67
- if (dataset.sublayers?.length) {
68
- return dataset.sublayers.flatMap(sublayer => {
69
- const { fillLayerId, strokeLayerId, symbolLayerId } = getSublayerLayerIds(dataset.id, sublayer.id)
70
- return [strokeLayerId, fillLayerId, symbolLayerId]
71
- })
72
- }
73
- const { fillLayerId, strokeLayerId, symbolLayerId } = getLayerIds(dataset)
74
- return [strokeLayerId, fillLayerId, symbolLayerId].filter(Boolean)
75
- }
@@ -1,27 +0,0 @@
1
- // Re-export pure pattern utilities from core — no map engine dependency.
2
- import { hasPattern } from '../../../../../../src/utils/patternUtils.js'
3
- import { mergeSublayer } from '../../utils/mergeSublayer.js'
4
-
5
- export { hasPattern } from '../../../../../../src/utils/patternUtils.js'
6
-
7
- /**
8
- * Returns a flat list of datasets and merged sublayers that require pattern images.
9
- * Handles sublayer merging so callers (e.g. mapProvider.addPatternsToMap) receive ready-to-use configs.
10
- *
11
- * @param {Object[]} datasets
12
- * @param {Object} patternRegistry
13
- * @returns {Object[]}
14
- */
15
- export const getPatternConfigs = (datasets, patternRegistry) =>
16
- datasets.flatMap(dataset => {
17
- const configs = hasPattern(dataset) ? [dataset] : []
18
- if (dataset.sublayers?.length) {
19
- dataset.sublayers.forEach(sublayer => {
20
- const merged = mergeSublayer(dataset, sublayer)
21
- if (hasPattern(merged)) {
22
- configs.push(merged)
23
- }
24
- })
25
- }
26
- return configs
27
- })
@@ -1,31 +0,0 @@
1
- // Re-export pure symbol resolution utilities from core — no map engine dependency.
2
- import { hasSymbol } from '../../../../../../src/utils/symbolUtils.js'
3
- import { mergeSublayer } from '../../utils/mergeSublayer.js'
4
-
5
- export { hasSymbol, getSymbolStyleColors, getSymbolViewBox, getSymbolAnchor } from '../../../../../../src/utils/symbolUtils.js'
6
-
7
- // Re-export MapLibre-specific symbol utilities from the provider.
8
- // This is the single cross-boundary import in the adapter; in a separate-package
9
- // setup this would be: '@interactive-map/maplibre-provider/utils/symbolImages'
10
- export { anchorToMaplibre } from '../../../../../../providers/maplibre/src/utils/symbolImages.js'
11
-
12
- /**
13
- * Returns a flat list of datasets and merged sublayers that require symbol images.
14
- * Handles sublayer merging so callers (e.g. mapProvider.addSymbolsToMap) receive ready-to-use configs.
15
- *
16
- * @param {Object[]} datasets
17
- * @returns {Object[]}
18
- */
19
- export const getSymbolConfigs = (datasets) =>
20
- datasets.flatMap(dataset => {
21
- const configs = hasSymbol(dataset) ? [dataset] : []
22
- if (dataset.sublayers?.length) {
23
- dataset.sublayers.forEach(sublayer => {
24
- const merged = mergeSublayer(dataset, sublayer)
25
- if (hasSymbol(merged)) {
26
- configs.push(merged)
27
- }
28
- })
29
- }
30
- return configs
31
- })
@@ -1,24 +0,0 @@
1
- import { hasSymbol } from '../../../../../src/utils/symbolUtils.js'
2
- import { hasPattern } from '../../../../../src/utils/patternUtils.js'
3
- import { KeySvgPattern } from './KeySvgPattern.jsx'
4
- import { KeySvgSymbol } from './KeySvgSymbol.jsx'
5
- import { KeySvgLine } from './KeySvgLine.jsx'
6
- import { KeySvgRect } from './KeySvgRect.jsx'
7
-
8
- export const KeySvg = (props) => {
9
- const { symbolRegistry } = props
10
- const symbolDef = hasSymbol(props) && symbolRegistry.getSymbolDef(props)
11
- if (symbolDef) {
12
- return <KeySvgSymbol {...props} symbolDef={symbolDef} />
13
- }
14
-
15
- if (hasPattern(props)) {
16
- return <KeySvgPattern {...props} />
17
- }
18
-
19
- if (props.keySymbolShape === 'line') {
20
- return <KeySvgLine {...props} />
21
- }
22
-
23
- return <KeySvgRect {...props} />
24
- }
@@ -1,19 +0,0 @@
1
- import { svgProps, SVG_SIZE, SVG_CENTER } from './svgProperties.js'
2
- import { getValueForStyle } from '../../../../../src/utils/getValueForStyle'
3
-
4
- export const KeySvgLine = (props) => {
5
- const { mapStyle } = props
6
- return (
7
- <svg {...svgProps}>
8
- <line
9
- x1={props.strokeWidth / 2}
10
- y1={SVG_CENTER}
11
- x2={SVG_SIZE - props.strokeWidth / 2}
12
- y2={SVG_CENTER}
13
- stroke={getValueForStyle(props.stroke, mapStyle.id)}
14
- strokeWidth={props.strokeWidth}
15
- strokeLinecap='round'
16
- />
17
- </svg>
18
- )
19
- }
@@ -1,22 +0,0 @@
1
- import { getValueForStyle } from '../../../../../src/utils/getValueForStyle'
2
- import { svgProps, SVG_SIZE } from './svgProperties.js'
3
-
4
- export const KeySvgRect = (props) => {
5
- const { mapStyle } = props
6
- return (
7
- <svg {...svgProps}>
8
- <rect
9
- x={props.strokeWidth / 2}
10
- y={props.strokeWidth / 2}
11
- width={SVG_SIZE - props.strokeWidth}
12
- height={SVG_SIZE - props.strokeWidth}
13
- rx={props.strokeWidth}
14
- ry={props.strokeWidth}
15
- fill={getValueForStyle(props.fill, mapStyle.id)}
16
- stroke={getValueForStyle(props.stroke, mapStyle.id)}
17
- strokeWidth={props.strokeWidth}
18
- strokeLinejoin='round'
19
- />
20
- </svg>
21
- )
22
- }
@@ -1,23 +0,0 @@
1
- import createDatasetsPlugin from './index.js'
2
-
3
- /**
4
- * Combined datasets plugin + MapLibre layer adapter for UMD consumers.
5
- *
6
- * Bakes the MapLibre adapter in so UMD users need a single script tag and no
7
- * layerAdapter config. The adapter is still loaded lazily — it is only fetched
8
- * when the datasets plugin initialises, not on page load.
9
- *
10
- * Both the manifest and adapter chunks are in the same webpack compilation so
11
- * cross-runtime module resolution issues are avoided.
12
- *
13
- * @example
14
- * const plugin = defra.datasetsMaplibrePlugin({ datasets: [...] })
15
- */
16
- export default function createDatasetsMaplibrePlugin (options = {}) {
17
- return createDatasetsPlugin({
18
- ...options,
19
- layerAdapter: {
20
- load: () => import(/* webpackChunkName: "im-datasets-maplibre-adapter" */ './adapters/maplibre/maplibreLayerAdapter.js')
21
- }
22
- })
23
- }
@@ -1,62 +0,0 @@
1
- import React from 'react'
2
- import { getValueForStyle } from '../../../../../src/utils/getValueForStyle'
3
- import { mergeSublayer } from '../utils/mergeSublayer.js'
4
- import { EmptyKey } from '../components/EmptyKey.jsx'
5
- import { KeySvg } from '../components/KeySvg.jsx'
6
-
7
- export const Key = ({ pluginConfig, mapState, pluginState, services }) => {
8
- if (!pluginState?.key?.items?.length) {
9
- return (<EmptyKey text={pluginConfig.noKeyItemText} />)
10
- }
11
- const { mapStyle } = mapState
12
- const { symbolRegistry, patternRegistry } = services
13
-
14
- const renderEntry = (key, config) => (
15
- <dl key={key} className='im-c-datasets-key__item'>
16
- <dt className='im-c-datasets-key__item-symbol'>
17
- <KeySvg {...config} symbolRegistry={symbolRegistry} patternRegistry={patternRegistry} mapStyle={mapStyle} />
18
- </dt>
19
- <dd className='im-c-datasets-key__item-label'>
20
- {config.label}
21
- {config.symbolDescription && (
22
- <span className='govuk-visually-hidden'>
23
- ({getValueForStyle(config.symbolDescription, mapStyle.id)})
24
- </span>
25
- )}
26
- </dd>
27
- </dl>
28
- )
29
-
30
- const { items: keyGroups, hasGroups } = pluginState.key
31
- const containerClass = `im-c-datasets-key${hasGroups ? ' im-c-datasets-key--has-groups' : ''}`
32
-
33
- return (
34
- <div className={containerClass}>
35
- {keyGroups.map(item => {
36
- if (item.type === 'sublayers') {
37
- const headingId = `key-heading-${item.dataset.id}`
38
- return (
39
- <section key={item.dataset.id} className='im-c-datasets-key__group' aria-labelledby={headingId}>
40
- <h3 id={headingId} className='im-c-datasets-key__group-heading'>{item.dataset.label}</h3>
41
- {item.dataset.sublayers
42
- .filter(sublayer => item.dataset.sublayerVisibility?.[sublayer.id] !== 'hidden')
43
- .map(sublayer => renderEntry(`${item.dataset.id}-${sublayer.id}`, mergeSublayer(item.dataset, sublayer)))}
44
- </section>
45
- )
46
- }
47
-
48
- if (item.type === 'group') {
49
- const headingId = `key-heading-${item.groupLabel.toLowerCase().replaceAll(/\s+/g, '-')}`
50
- return (
51
- <section key={item.groupLabel} className='im-c-datasets-key__group' aria-labelledby={headingId}>
52
- <h3 id={headingId} className='im-c-datasets-key__group-heading'>{item.groupLabel}</h3>
53
- {item.datasets.map(dataset => renderEntry(dataset.id, dataset))}
54
- </section>
55
- )
56
- }
57
-
58
- return renderEntry(item.dataset.id, item.dataset)
59
- })}
60
- </div>
61
- )
62
- }
@@ -1,141 +0,0 @@
1
- import React from 'react'
2
- import { setDatasetVisibility } from '../api/setDatasetVisibility'
3
-
4
- const CHECKBOX_LABEL_CLASS = 'im-c-datasets-layers__item-label govuk-label govuk-checkboxes__label'
5
-
6
- const hasToggleableSublayers = (dataset) => dataset.sublayers?.some(sublayer => sublayer.showInMenu)
7
-
8
- /**
9
- * Collapse the filtered dataset list into ordered render items:
10
- * { type: 'sublayers', dataset } — dataset with sublayers (takes precedence)
11
- * { type: 'group', groupLabel, datasets } — datasets sharing a groupLabel
12
- * { type: 'flat', dataset } — standalone dataset
13
- */
14
- const buildRenderItems = (datasets) => {
15
- const seenGroups = new Set()
16
- const items = []
17
- datasets.forEach(dataset => {
18
- if (hasToggleableSublayers(dataset)) {
19
- items.push({ type: 'sublayers', dataset })
20
- return
21
- }
22
- if (dataset.groupLabel) {
23
- if (seenGroups.has(dataset.groupLabel)) {
24
- return
25
- }
26
- seenGroups.add(dataset.groupLabel)
27
- items.push({
28
- type: 'group',
29
- groupLabel: dataset.groupLabel,
30
- datasets: datasets.filter(d => !hasToggleableSublayers(d) && d.groupLabel === dataset.groupLabel)
31
- })
32
- return
33
- }
34
- items.push({ type: 'flat', dataset })
35
- })
36
- return items
37
- }
38
-
39
- export const Layers = ({ pluginState }) => {
40
- const handleDatasetChange = (e) => {
41
- const { value, checked } = e.target
42
- setDatasetVisibility({ pluginState }, checked, { datasetId: value })
43
- }
44
-
45
- const handleSublayerChange = (e) => {
46
- const { checked } = e.target
47
- const datasetId = e.target.dataset.datasetId
48
- const sublayerId = e.target.dataset.sublayerId
49
- setDatasetVisibility({ pluginState }, checked, { datasetId, sublayerId })
50
- }
51
-
52
- const renderDatasetItem = (dataset) => {
53
- const itemClass = `im-c-datasets-layers__item govuk-checkboxes govuk-checkboxes--small${dataset.visibility === 'hidden' ? '' : ' im-c-datasets-layers__item--checked'}`
54
- return (
55
- <div key={dataset.id} className={itemClass} data-module='govuk-checkboxes'>
56
- <div className='govuk-checkboxes__item'>
57
- <input
58
- className='govuk-checkboxes__input'
59
- id={dataset.id}
60
- name='layers'
61
- type='checkbox'
62
- value={dataset.id}
63
- checked={dataset.visibility !== 'hidden'}
64
- onChange={handleDatasetChange}
65
- />
66
- <label className={CHECKBOX_LABEL_CLASS} htmlFor={dataset.id}>
67
- {dataset.label}
68
- </label>
69
- </div>
70
- </div>
71
- )
72
- }
73
-
74
- const visibleDatasets = (pluginState.datasets || [])
75
- .filter(dataset => dataset.showInMenu || hasToggleableSublayers(dataset))
76
-
77
- const renderItems = buildRenderItems(visibleDatasets)
78
- const hasGroups = renderItems.some(item => item.type === 'sublayers' || item.type === 'group')
79
- const containerClass = `im-c-datasets-layers${hasGroups ? ' im-c-datasets-layers--has-groups' : ''}`
80
-
81
- return (
82
- <div className={containerClass}>
83
- {renderItems.map(item => {
84
- if (item.type === 'sublayers') {
85
- const { dataset } = item
86
- const anySublayerChecked = dataset.sublayers
87
- .filter(sublayer => sublayer.showInMenu)
88
- .some(sublayer => dataset.sublayerVisibility?.[sublayer.id] !== 'hidden')
89
- const wrapperClass = `govuk-form-group im-c-datasets-layers-group${anySublayerChecked ? ' im-c-datasets-layers-group--items-checked' : ''}`
90
- return (
91
- <div key={dataset.id} className={wrapperClass}>
92
- <fieldset className='im-c-datasets-layers-group__fieldset'>
93
- <legend className='im-c-datasets-layers-group__legend'>{dataset.label}</legend>
94
- {dataset.sublayers
95
- .filter(sublayer => sublayer.showInMenu)
96
- .map(sublayer => {
97
- const sublayerVisible = dataset.sublayerVisibility?.[sublayer.id] !== 'hidden'
98
- const inputId = `${dataset.id}-${sublayer.id}`
99
- const itemClass = `im-c-datasets-layers__item govuk-checkboxes govuk-checkboxes--small${sublayerVisible ? ' im-c-datasets-layers__item--checked' : ''}`
100
- return (
101
- <div key={sublayer.id} className={itemClass} data-module='govuk-checkboxes'>
102
- <div className='govuk-checkboxes__item'>
103
- <input
104
- className='govuk-checkboxes__input'
105
- id={inputId}
106
- type='checkbox'
107
- checked={sublayerVisible}
108
- data-dataset-id={dataset.id}
109
- data-sublayer-id={sublayer.id}
110
- onChange={handleSublayerChange}
111
- />
112
- <label className={CHECKBOX_LABEL_CLASS} htmlFor={inputId}>
113
- {sublayer.label}
114
- </label>
115
- </div>
116
- </div>
117
- )
118
- })}
119
- </fieldset>
120
- </div>
121
- )
122
- }
123
-
124
- if (item.type === 'group') {
125
- const anyDatasetChecked = item.datasets.some(d => d.visibility !== 'hidden')
126
- const wrapperClass = `govuk-form-group im-c-datasets-layers-group${anyDatasetChecked ? ' im-c-datasets-layers-group--items-checked' : ''}`
127
- return (
128
- <div key={item.groupLabel} className={wrapperClass}>
129
- <fieldset className='im-c-datasets-layers-group__fieldset'>
130
- <legend className='im-c-datasets-layers-group__legend'>{item.groupLabel}</legend>
131
- {item.datasets.map(dataset => renderDatasetItem(dataset))}
132
- </fieldset>
133
- </div>
134
- )
135
- }
136
-
137
- return renderDatasetItem(item.dataset)
138
- })}
139
- </div>
140
- )
141
- }
@@ -1,219 +0,0 @@
1
- import { applyDatasetDefaults } from './defaults.js'
2
- import { keyReducer } from './reducers/keyReducer.js'
3
-
4
- const initialState = {
5
- datasets: null,
6
- key: {
7
- items: [],
8
- hasGroups: false
9
- },
10
- hiddenFeatures: {}, // { [layerId]: { idProperty: string, ids: string[] } }
11
- layerAdapter: null
12
- }
13
-
14
- const initSublayerVisibility = (dataset) => {
15
- if (!dataset.sublayers?.length) {
16
- return dataset
17
- }
18
- const sublayerVisibility = {}
19
- dataset.sublayers.forEach(sublayer => {
20
- sublayerVisibility[sublayer.id] = 'visible'
21
- })
22
- return { ...dataset, sublayerVisibility }
23
- }
24
-
25
- const setDatasets = (state, payload) => {
26
- const { datasets, datasetDefaults } = payload
27
- return {
28
- ...state,
29
- datasets: datasets.map(dataset => initSublayerVisibility(applyDatasetDefaults(dataset, datasetDefaults)))
30
- }
31
- }
32
-
33
- const addDataset = (state, payload) => {
34
- const { dataset, datasetDefaults } = payload
35
- return {
36
- ...state,
37
- datasets: [
38
- ...(state.datasets || []),
39
- initSublayerVisibility(applyDatasetDefaults(dataset, datasetDefaults))
40
- ]
41
- }
42
- }
43
-
44
- const removeDataset = (state, payload) => {
45
- const { id } = payload
46
- return {
47
- ...state,
48
- datasets: state.datasets?.filter(dataset => dataset.id !== id) || []
49
- }
50
- }
51
-
52
- const setDatasetVisibility = (state, payload) => {
53
- const { id, visibility } = payload
54
- return {
55
- ...state,
56
- datasets: state.datasets?.map(dataset =>
57
- dataset.id === id ? { ...dataset, visibility } : dataset
58
- )
59
- }
60
- }
61
-
62
- const setGlobalVisibility = (state, payload) => {
63
- const { visibility } = payload
64
- return {
65
- ...state,
66
- datasets: state.datasets?.map(dataset => ({ ...dataset, visibility }))
67
- }
68
- }
69
-
70
- const hideFeatures = (state, payload) => {
71
- const { layerId, idProperty, featureIds } = payload
72
- const existing = state.hiddenFeatures[layerId]
73
- const existingIds = existing?.ids || []
74
- const newIds = [...new Set([...existingIds, ...featureIds])]
75
-
76
- return {
77
- ...state,
78
- hiddenFeatures: {
79
- ...state.hiddenFeatures,
80
- [layerId]: { idProperty, ids: newIds }
81
- }
82
- }
83
- }
84
-
85
- const showFeatures = (state, payload) => {
86
- const { layerId, featureIds } = payload
87
- const existing = state.hiddenFeatures[layerId]
88
- if (!existing) {
89
- return state
90
- }
91
-
92
- const newIds = existing.ids.filter(id => !featureIds.includes(id))
93
-
94
- if (newIds.length === 0) {
95
- const rest = { ...state.hiddenFeatures }
96
- delete rest[layerId]
97
- return { ...state, hiddenFeatures: rest }
98
- }
99
-
100
- return {
101
- ...state,
102
- hiddenFeatures: {
103
- ...state.hiddenFeatures,
104
- [layerId]: { ...existing, ids: newIds }
105
- }
106
- }
107
- }
108
-
109
- const setSublayerVisibility = (state, payload) => {
110
- const { datasetId, sublayerId, visibility } = payload
111
- return {
112
- ...state,
113
- datasets: state.datasets?.map(dataset => {
114
- if (dataset.id !== datasetId) {
115
- return dataset
116
- }
117
- return {
118
- ...dataset,
119
- sublayerVisibility: {
120
- ...dataset.sublayerVisibility,
121
- [sublayerId]: visibility
122
- }
123
- }
124
- })
125
- }
126
- }
127
-
128
- const setDatasetStyle = (state, payload) => {
129
- const { datasetId, styleChanges } = payload
130
- return {
131
- ...state,
132
- datasets: state.datasets?.map(dataset =>
133
- dataset.id === datasetId ? { ...dataset, ...styleChanges } : dataset
134
- )
135
- }
136
- }
137
-
138
- const setSublayerStyle = (state, payload) => {
139
- const { datasetId, sublayerId, styleChanges } = payload
140
- return {
141
- ...state,
142
- datasets: state.datasets?.map(dataset => {
143
- if (dataset.id !== datasetId) {
144
- return dataset
145
- }
146
- return {
147
- ...dataset,
148
- sublayers: dataset.sublayers?.map(sublayer =>
149
- sublayer.id === sublayerId
150
- ? { ...sublayer, style: { ...sublayer.style, ...styleChanges } }
151
- : sublayer
152
- )
153
- }
154
- })
155
- }
156
- }
157
-
158
- const setOpacity = (state, payload) => {
159
- const { datasetId, opacity } = payload
160
- return {
161
- ...state,
162
- datasets: state.datasets?.map(dataset =>
163
- dataset.id === datasetId ? { ...dataset, opacity } : dataset
164
- )
165
- }
166
- }
167
-
168
- const setGlobalOpacity = (state, payload) => {
169
- const { opacity } = payload
170
- return {
171
- ...state,
172
- datasets: state.datasets?.map(dataset => ({ ...dataset, opacity }))
173
- }
174
- }
175
-
176
- const setSublayerOpacity = (state, payload) => {
177
- const { datasetId, sublayerId, opacity } = payload
178
- return {
179
- ...state,
180
- datasets: state.datasets?.map(dataset => {
181
- if (dataset.id !== datasetId) {
182
- return dataset
183
- }
184
- return {
185
- ...dataset,
186
- sublayers: dataset.sublayers?.map(sublayer =>
187
- sublayer.id === sublayerId
188
- ? { ...sublayer, style: { ...sublayer.style, opacity } }
189
- : sublayer
190
- )
191
- }
192
- })
193
- }
194
- }
195
-
196
- const setLayerAdapter = (state, payload) => ({ ...state, layerAdapter: payload })
197
-
198
- const actions = {
199
- BUILD_KEY_GROUPS: keyReducer,
200
- SET_DATASETS: setDatasets,
201
- ADD_DATASET: addDataset,
202
- REMOVE_DATASET: removeDataset,
203
- SET_DATASET_VISIBILITY: setDatasetVisibility,
204
- SET_GLOBAL_VISIBILITY: setGlobalVisibility,
205
- SET_SUBLAYER_VISIBILITY: setSublayerVisibility,
206
- SET_DATASET_STYLE: setDatasetStyle,
207
- SET_SUBLAYER_STYLE: setSublayerStyle,
208
- SET_OPACITY: setOpacity,
209
- SET_GLOBAL_OPACITY: setGlobalOpacity,
210
- SET_SUBLAYER_OPACITY: setSublayerOpacity,
211
- HIDE_FEATURES: hideFeatures,
212
- SHOW_FEATURES: showFeatures,
213
- SET_LAYER_ADAPTER: setLayerAdapter
214
- }
215
-
216
- export {
217
- initialState,
218
- actions
219
- }
@@ -1,34 +0,0 @@
1
- export const keyReducer = (state) => {
2
- const datasets = state.datasets || []
3
- const seenGroups = new Set()
4
- const items = []
5
- let hasGroups = false
6
- datasets.forEach(dataset => {
7
- if (!dataset.showInKey || dataset.visibility === 'hidden') {
8
- return
9
- }
10
- if (dataset.sublayers?.length) {
11
- const { sublayerVisibility = [] } = dataset
12
- if (Object.values(sublayerVisibility).some((value) => value !== 'hidden')) {
13
- hasGroups = true
14
- items.push({ type: 'sublayers', dataset })
15
- }
16
- return
17
- }
18
- if (dataset.groupLabel) {
19
- if (seenGroups.has(dataset.groupLabel)) {
20
- return
21
- }
22
- seenGroups.add(dataset.groupLabel)
23
- hasGroups = true
24
- items.push({
25
- type: 'group',
26
- groupLabel: dataset.groupLabel,
27
- datasets: datasets.filter(d => !d.sublayers?.length && d.groupLabel === dataset.groupLabel)
28
- })
29
- return
30
- }
31
- items.push({ type: 'flat', dataset })
32
- })
33
- return { ...state, key: { items, hasGroups } }
34
- }