@defra/interactive-map 0.0.16-alpha → 0.0.17-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 (130) hide show
  1. package/assets/images/slot-map.svg +264 -0
  2. package/dist/css/index.css +1 -1
  3. package/dist/esm/im-core.js +1 -1
  4. package/dist/esm/im-shell.js +1 -1
  5. package/dist/umd/im-core.js +1 -1
  6. package/dist/umd/index.js +1 -1
  7. package/docs/api/slots.md +16 -15
  8. package/docs/api.md +3 -3
  9. package/docs/getting-started.md +4 -1
  10. package/docs/plugins/datasets.md +561 -0
  11. package/docs/plugins.md +1 -1
  12. package/package.json +2 -2
  13. package/plugins/beta/datasets/dist/css/index.css +85 -15
  14. package/plugins/beta/datasets/dist/esm/im-datasets-plugin.js +1 -1
  15. package/plugins/beta/datasets/dist/umd/im-datasets-plugin.js +1 -1
  16. package/plugins/beta/datasets/dist/umd/index.js +1 -1
  17. package/plugins/beta/datasets/src/DatasetsInit.jsx +23 -8
  18. package/plugins/beta/datasets/src/adapters/maplibre/index.js +18 -0
  19. package/plugins/beta/datasets/src/adapters/maplibre/layerBuilders.js +113 -0
  20. package/plugins/beta/datasets/src/adapters/maplibre/layerIds.js +69 -0
  21. package/plugins/beta/datasets/src/adapters/maplibre/maplibreLayerAdapter.js +338 -0
  22. package/plugins/beta/datasets/src/adapters/maplibre/patternRegistry.js +48 -0
  23. package/plugins/beta/datasets/src/api/addDataset.js +2 -8
  24. package/plugins/beta/datasets/src/api/getOpacity.js +17 -0
  25. package/plugins/beta/datasets/src/api/getStyle.js +13 -0
  26. package/plugins/beta/datasets/src/api/removeDataset.js +2 -44
  27. package/plugins/beta/datasets/src/api/setData.js +8 -0
  28. package/plugins/beta/datasets/src/api/setDatasetVisibility.js +37 -0
  29. package/plugins/beta/datasets/src/api/setFeatureVisibility.js +22 -0
  30. package/plugins/beta/datasets/src/api/setOpacity.js +29 -0
  31. package/plugins/beta/datasets/src/api/setStyle.js +22 -0
  32. package/plugins/beta/datasets/src/datasets.js +29 -55
  33. package/plugins/beta/datasets/src/defaults.js +42 -8
  34. package/plugins/beta/datasets/src/fetch/createDynamicSource.js +34 -25
  35. package/plugins/beta/datasets/src/fetch/fetchGeoJSON.js +2 -2
  36. package/plugins/beta/datasets/src/manifest.js +24 -16
  37. package/plugins/beta/datasets/src/panels/Key.jsx +128 -50
  38. package/plugins/beta/datasets/src/panels/Key.module.scss +48 -9
  39. package/plugins/beta/datasets/src/panels/Layers.jsx +132 -29
  40. package/plugins/beta/datasets/src/panels/Layers.module.scss +50 -8
  41. package/plugins/beta/datasets/src/reducer.js +128 -9
  42. package/plugins/beta/datasets/src/styles/patterns.js +157 -0
  43. package/plugins/beta/datasets/src/utils/bbox.js +7 -5
  44. package/plugins/beta/datasets/src/utils/filters.js +5 -2
  45. package/plugins/beta/datasets/src/utils/mergeSublayer.js +78 -0
  46. package/plugins/beta/draw-ml/dist/css/index.css +1 -1
  47. package/plugins/beta/draw-ml/dist/esm/im-draw-ml-plugin.js +1 -1
  48. package/plugins/beta/draw-ml/dist/umd/im-draw-ml-plugin.js +1 -1
  49. package/plugins/beta/draw-ml/src/draw.scss +0 -7
  50. package/plugins/beta/draw-ml/src/manifest.js +16 -16
  51. package/plugins/beta/frame/dist/esm/im-frame-plugin.js +1 -1
  52. package/plugins/beta/frame/dist/umd/im-frame-plugin.js +1 -1
  53. package/plugins/beta/frame/src/Frame.jsx +5 -5
  54. package/plugins/beta/map-styles/dist/esm/im-map-styles-plugin.js +1 -1
  55. package/plugins/beta/map-styles/dist/umd/im-map-styles-plugin.js +1 -1
  56. package/plugins/beta/map-styles/src/manifest.js +1 -1
  57. package/plugins/beta/scale-bar/dist/css/index.css +1 -1
  58. package/plugins/beta/scale-bar/dist/esm/im-scale-bar-plugin.js +1 -1
  59. package/plugins/beta/scale-bar/dist/umd/im-scale-bar-plugin.js +1 -1
  60. package/plugins/beta/scale-bar/src/index.test.js +3 -3
  61. package/plugins/beta/scale-bar/src/manifest.js +3 -3
  62. package/plugins/beta/scale-bar/src/scaleBar.scss +2 -1
  63. package/plugins/interact/dist/css/index.css +1 -1
  64. package/plugins/interact/dist/esm/im-interact-plugin.js +1 -1
  65. package/plugins/interact/dist/umd/im-interact-plugin.js +1 -1
  66. package/plugins/interact/src/interact.scss +0 -7
  67. package/plugins/interact/src/manifest.js +14 -18
  68. package/plugins/interact/src/manifest.test.js +3 -1
  69. package/plugins/search/dist/css/index.css +1 -1
  70. package/plugins/search/src/components/Form/Form.module.scss +2 -1
  71. package/providers/maplibre/dist/esm/im-maplibre-provider.js +1 -1
  72. package/providers/maplibre/dist/umd/im-maplibre-framework.js +1 -1
  73. package/providers/maplibre/dist/umd/im-maplibre-framework.js.LICENSE.txt +1 -1
  74. package/providers/maplibre/dist/umd/im-maplibre-provider.js +1 -1
  75. package/providers/maplibre/src/utils/highlightFeatures.js +1 -0
  76. package/providers/maplibre/src/utils/highlightFeatures.test.js +1 -0
  77. package/src/App/components/Actions/Actions.jsx +2 -2
  78. package/src/App/components/Actions/Actions.module.scss +0 -7
  79. package/src/App/components/Actions/Actions.test.jsx +1 -1
  80. package/src/App/components/Icon/Icon.jsx +3 -2
  81. package/src/App/components/Icon/Icon.module.scss +4 -0
  82. package/src/App/components/Icon/Icon.test.jsx +43 -4
  83. package/src/App/components/MapButton/MapButton.jsx +42 -17
  84. package/src/App/components/MapButton/MapButton.module.scss +4 -13
  85. package/src/App/components/MapButton/MapButton.test.jsx +27 -3
  86. package/src/App/components/PopupMenu/PopupMenu.jsx +51 -274
  87. package/src/App/components/PopupMenu/PopupMenu.module.scss +14 -7
  88. package/src/App/components/PopupMenu/PopupMenu.test.jsx +70 -1
  89. package/src/App/components/PopupMenu/usePopupMenu.js +258 -0
  90. package/src/App/hooks/useButtonStateEvaluator.js +12 -2
  91. package/src/App/hooks/useButtonStateEvaluator.test.js +38 -4
  92. package/src/App/hooks/useInterfaceAPI.js +6 -0
  93. package/src/App/hooks/useLayoutMeasurements.js +84 -18
  94. package/src/App/hooks/useLayoutMeasurements.test.js +124 -17
  95. package/src/App/layout/Layout.jsx +12 -7
  96. package/src/App/layout/Layout.test.jsx +2 -2
  97. package/src/App/layout/layout.module.scss +67 -29
  98. package/src/App/registry/pluginRegistry.js +1 -1
  99. package/src/App/renderer/HtmlElementHost.jsx +2 -1
  100. package/src/App/renderer/HtmlElementHost.test.jsx +7 -7
  101. package/src/App/renderer/mapButtons.js +1 -1
  102. package/src/App/renderer/mapPanels.test.js +2 -2
  103. package/src/App/renderer/slotHelpers.js +2 -2
  104. package/src/App/renderer/slotHelpers.test.js +5 -5
  105. package/src/App/renderer/slots.js +9 -5
  106. package/src/App/store/AppProvider.jsx +3 -1
  107. package/src/App/store/AppProvider.test.jsx +1 -1
  108. package/src/App/store/ServiceProvider.jsx +3 -1
  109. package/src/App/store/appActionsMap.js +16 -0
  110. package/src/App/store/appActionsMap.test.js +27 -0
  111. package/src/App/store/appDispatchMiddleware.js +1 -1
  112. package/src/App/store/appDispatchMiddleware.test.js +2 -2
  113. package/src/App/store/appReducer.js +2 -0
  114. package/src/InteractiveMap/InteractiveMap.js +4 -0
  115. package/src/config/appConfig.js +5 -2
  116. package/src/config/events.js +28 -0
  117. package/src/scss/main.scss +1 -0
  118. package/src/scss/settings/_dimensions.scss +0 -1
  119. package/src/utils/getSafeZoneInset.js +9 -7
  120. package/src/utils/getSafeZoneInset.test.js +10 -10
  121. package/webpack.dev.mjs +1 -1
  122. package/docs/api/slot-map.svg +0 -1
  123. package/plugins/beta/datasets/src/api/hideDataset.js +0 -14
  124. package/plugins/beta/datasets/src/api/hideFeatures.js +0 -41
  125. package/plugins/beta/datasets/src/api/showDataset.js +0 -14
  126. package/plugins/beta/datasets/src/api/showFeatures.js +0 -44
  127. package/plugins/beta/datasets/src/handleSetMapStyle.js +0 -54
  128. package/plugins/beta/datasets/src/mapLayers.js +0 -164
  129. /package/src/{utils → services}/logger.js +0 -0
  130. /package/src/{utils → services}/logger.test.js +0 -0
@@ -22,7 +22,7 @@ export const bboxContains = (outer, inner) => {
22
22
  inner[0] >= outer[0] && // west
23
23
  inner[1] >= outer[1] && // south
24
24
  inner[2] <= outer[2] && // east
25
- inner[3] <= outer[3] // north
25
+ inner[3] <= outer[3] // NOSONAR, north
26
26
  )
27
27
  }
28
28
 
@@ -40,7 +40,7 @@ export const expandBbox = (existing, addition) => {
40
40
  Math.min(existing[0], addition[0]), // west
41
41
  Math.min(existing[1], addition[1]), // south
42
42
  Math.max(existing[2], addition[2]), // east
43
- Math.max(existing[3], addition[3]) // north
43
+ Math.max(existing[3], addition[3]) // NOSONAR, north
44
44
  ]
45
45
  }
46
46
 
@@ -57,8 +57,8 @@ export const bboxIntersects = (a, b) => {
57
57
  return !(
58
58
  a[2] < b[0] || // a is left of b
59
59
  a[0] > b[2] || // a is right of b
60
- a[3] < b[1] || // a is below b
61
- a[1] > b[3] // a is above b
60
+ a[3] < b[1] || // NOSONAR a is below b
61
+ a[1] > b[3] // NOSONAR a is above b
62
62
  )
63
63
  }
64
64
 
@@ -98,7 +98,7 @@ export const getGeometryBbox = (geometry) => {
98
98
  processCoords(geometry.coordinates, 2)
99
99
  break
100
100
  case 'MultiPolygon':
101
- processCoords(geometry.coordinates, 3)
101
+ processCoords(geometry.coordinates, 3) // NOSONAR: 3 = coordinate nesting depth for MultiPolygon ([polygons][rings][points])
102
102
  break
103
103
  case 'GeometryCollection':
104
104
  geometry.geometries.forEach(g => {
@@ -109,6 +109,8 @@ export const getGeometryBbox = (geometry) => {
109
109
  maxY = Math.max(maxY, b[3])
110
110
  })
111
111
  break
112
+ default:
113
+ throw new Error(`Unsupported geometry type: ${geometry.type}`)
112
114
  }
113
115
 
114
116
  return [minX, minY, maxX, maxY]
@@ -8,8 +8,11 @@ export const buildExclusionFilter = (originalFilter, idProperty, excludeIds) =>
8
8
  }
9
9
 
10
10
  // Coerce both sides to strings to handle number/string type mismatches
11
- const stringIds = excludeIds.map(id => String(id))
12
- const exclusionFilter = ['!', ['in', ['to-string', ['get', idProperty]], ['literal', stringIds]]]
11
+ // When no idProperty, use feature-level id via ['id'] (GeoJSON feature.id)
12
+ const idExpr = idProperty ? ['to-string', ['get', idProperty]] : ['to-string', ['id']]
13
+ // Convert all IDs to strings; map passes each element as the first argument to String
14
+ const stringIds = excludeIds.map(String)
15
+ const exclusionFilter = ['!', ['in', idExpr, ['literal', stringIds]]]
13
16
 
14
17
  if (!originalFilter) {
15
18
  return exclusionFilter
@@ -0,0 +1,78 @@
1
+ import { hasCustomVisualStyle } from '../defaults.js'
2
+
3
+ const getFillProps = (dataset, sublayerStyle) => {
4
+ if (sublayerStyle.fillPattern || sublayerStyle.fillPatternSvgContent) {
5
+ return {
6
+ fillPattern: sublayerStyle.fillPattern,
7
+ fillPatternSvgContent: sublayerStyle.fillPatternSvgContent,
8
+ fillPatternForegroundColor: sublayerStyle.fillPatternForegroundColor ?? dataset.fillPatternForegroundColor,
9
+ fillPatternBackgroundColor: sublayerStyle.fillPatternBackgroundColor ?? dataset.fillPatternBackgroundColor
10
+ }
11
+ }
12
+ if ('fill' in sublayerStyle) {
13
+ // Sublayer explicitly sets a plain fill — do not inherit any parent pattern
14
+ return { fill: sublayerStyle.fill }
15
+ }
16
+ return {
17
+ fill: dataset.fill,
18
+ fillPattern: dataset.fillPattern,
19
+ fillPatternSvgContent: dataset.fillPatternSvgContent,
20
+ fillPatternForegroundColor: dataset.fillPatternForegroundColor,
21
+ fillPatternBackgroundColor: dataset.fillPatternBackgroundColor
22
+ }
23
+ }
24
+
25
+ const getCombinedFilter = (datasetFilter, sublayerFilter) => {
26
+ if (datasetFilter && sublayerFilter) {
27
+ return ['all', datasetFilter, sublayerFilter]
28
+ }
29
+ return sublayerFilter || datasetFilter || null
30
+ }
31
+
32
+ const getSymbolDescription = (dataset, sublayerStyle) => {
33
+ if ('symbolDescription' in sublayerStyle) {
34
+ return sublayerStyle.symbolDescription
35
+ }
36
+ if (hasCustomVisualStyle(sublayerStyle)) {
37
+ return undefined
38
+ }
39
+ return dataset.symbolDescription
40
+ }
41
+
42
+ /**
43
+ * Merge a sublayer with its parent dataset, producing a flat style
44
+ * object suitable for layer creation and key symbol rendering.
45
+ *
46
+ * The sublayer's nested `style` object is flattened before merging.
47
+ *
48
+ * Fill precedence (highest to lowest):
49
+ * 1. Sublayer's own fillPattern
50
+ * 2. Sublayer's own fill (explicit, even if transparent — clears any parent pattern)
51
+ * 3. Parent's fillPattern
52
+ * 4. Parent's fill
53
+ *
54
+ * symbolDescription is only inherited from the parent when the sublayer has no
55
+ * custom visual styles of its own. If the sublayer overrides stroke/fill/pattern
56
+ * without setting symbolDescription explicitly, no description is shown.
57
+ */
58
+ export const mergeSublayer = (dataset, sublayer) => {
59
+ const sublayerStyle = sublayer.style || {}
60
+ const combinedFilter = getCombinedFilter(dataset.filter, sublayer.filter)
61
+
62
+ return {
63
+ id: sublayer.id,
64
+ label: sublayer.label,
65
+ stroke: sublayerStyle.stroke ?? dataset.stroke,
66
+ strokeWidth: sublayerStyle.strokeWidth ?? dataset.strokeWidth,
67
+ strokeDashArray: sublayerStyle.strokeDashArray ?? dataset.strokeDashArray,
68
+ opacity: sublayerStyle.opacity ?? dataset.opacity,
69
+ keySymbolShape: sublayerStyle.keySymbolShape ?? dataset.keySymbolShape,
70
+ symbolDescription: getSymbolDescription(dataset, sublayerStyle),
71
+ showInKey: sublayer.showInKey ?? dataset.showInKey,
72
+ toggleVisibility: sublayer.toggleVisibility ?? false,
73
+ filter: combinedFilter,
74
+ minZoom: dataset.minZoom,
75
+ maxZoom: dataset.maxZoom,
76
+ ...getFillProps(dataset, sublayerStyle)
77
+ }
78
+ }
@@ -1 +1 @@
1
- .touch-vertex-target circle{fill:var(--map-overlay-foreground-color)}.touch-vertex-target path{fill:var(--map-overlay-halo-color)}.im-c-actions .im-c-button-wrapper--draw-done,.im-c-actions .im-c-button-wrapper--draw-menu,.im-c-actions .im-c-button-wrapper--draw-cancel{width:33.33%}.im-o-app--tablet .im-c-actions .im-c-button-wrapper--draw-done,.im-o-app--tablet .im-c-actions .im-c-button-wrapper--draw-menu,.im-o-app--tablet .im-c-actions .im-c-button-wrapper--draw-cancel,.im-o-app--desktop .im-c-actions .im-c-button-wrapper--draw-done,.im-o-app--desktop .im-c-actions .im-c-button-wrapper--draw-menu,.im-o-app--desktop .im-c-actions .im-c-button-wrapper--draw-cancel{width:100px}.im-c-button-wrapper--draw-add-point{position:absolute;bottom:calc(100% + var(--primary-gap));z-index:0}
1
+ .touch-vertex-target circle{fill:var(--map-overlay-foreground-color)}.touch-vertex-target path{fill:var(--map-overlay-halo-color)}.im-c-actions .im-c-button-wrapper--draw-done,.im-c-actions .im-c-button-wrapper--draw-menu,.im-c-actions .im-c-button-wrapper--draw-cancel{width:33.33%}.im-o-app--tablet .im-c-actions .im-c-button-wrapper--draw-done,.im-o-app--tablet .im-c-actions .im-c-button-wrapper--draw-menu,.im-o-app--tablet .im-c-actions .im-c-button-wrapper--draw-cancel,.im-o-app--desktop .im-c-actions .im-c-button-wrapper--draw-done,.im-o-app--desktop .im-c-actions .im-c-button-wrapper--draw-menu,.im-o-app--desktop .im-c-actions .im-c-button-wrapper--draw-cancel{width:100px}