@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
@@ -6,10 +6,8 @@ The datasets plugin renders GeoJSON and vector tile datasets on the map, with su
6
6
 
7
7
  ```js
8
8
  import createDatasetsPlugin from '@defra/interactive-map/plugins/datasets'
9
- import { maplibreLayerAdapter } from '@defra/interactive-map/plugins/datasets/adapters/maplibre'
10
9
 
11
10
  const datasetsPlugin = createDatasetsPlugin({
12
- layerAdapter: maplibreLayerAdapter,
13
11
  datasets: [
14
12
  {
15
13
  id: 'my-parcels',
@@ -35,14 +33,14 @@ const interactiveMap = new InteractiveMap({
35
33
 
36
34
  ## UMD usage
37
35
 
38
- Copy `plugins/beta/datasets/dist/umd/maplibre/` to `/your-assets-path/plugins/beta/datasets/umd/maplibre/`, then load the script tag. The MapLibre adapter is included no `layerAdapter` config is needed.
36
+ Copy the entire `plugins/beta/datasets/dist/umd/` directory to `/your-assets-path/plugins/beta/datasets/umd/`. The plugin uses dynamic imports, so all files in the directory must be served from the same location. Then add the script tag:
39
37
 
40
38
  ```html
41
- <script defer src="/your-assets-path/plugins/beta/datasets/umd/maplibre/index.js"></script>
39
+ <script defer src="/your-assets-path/plugins/beta/datasets/umd/index.js"></script>
42
40
  ```
43
41
 
44
42
  ```js
45
- const datasetsPlugin = defra.datasetsMaplibrePlugin({
43
+ const datasetsPlugin = defra.datasetsPlugin({
46
44
  datasets: [
47
45
  {
48
46
  id: 'my-parcels',
@@ -60,12 +58,17 @@ const datasetsPlugin = defra.datasetsMaplibrePlugin({
60
58
  }
61
59
  ]
62
60
  })
61
+
62
+ const interactiveMap = new defra.InteractiveMap('map', {
63
+ mapProvider: defra.maplibreProvider(),
64
+ plugins: [datasetsPlugin]
65
+ })
63
66
  ```
64
67
 
65
68
  > [!NOTE]
66
- > **GOV.UK Prototype Kit** — skip the copy step. The file is served automatically. Use this path instead:
69
+ > **GOV.UK Prototype Kit** — skip the copy step. All files are served automatically. Use this path instead:
67
70
  > ```html
68
- > <script defer src="/plugin-assets/%40defra%2Finteractive-map/plugins/beta/datasets/dist/umd/maplibre/index.js"></script>
71
+ > <script defer src="/plugin-assets/%40defra%2Finteractive-map/plugins/beta/datasets/dist/umd/index.js"></script>
69
72
  > ```
70
73
 
71
74
  ## Options
@@ -74,22 +77,6 @@ Options are passed to the factory function when creating the plugin.
74
77
 
75
78
  ---
76
79
 
77
- ### `layerAdapter`
78
-
79
- > [!NOTE]
80
- > UMD users using the `datasetsMaplibrePlugin` bundle do not need to set this — the MapLibre adapter is pre-configured.
81
-
82
- **Type:** `LayerAdapter`
83
- **Required**
84
-
85
- The map provider adapter responsible for rendering datasets. Import `maplibreLayerAdapter` for MapLibre GL JS, or supply a custom adapter.
86
-
87
- ```js
88
- import { maplibreLayerAdapter } from '@defra/interactive-map/plugins/datasets/adapters/maplibre'
89
- ```
90
-
91
- ---
92
-
93
80
  ### `datasets`
94
81
 
95
82
  **Type:** `Dataset[]`
@@ -134,7 +121,7 @@ Unique identifier for the dataset. Used in all API method calls.
134
121
 
135
122
  **Type:** `string`
136
123
 
137
- Human-readable name shown in the Layers panel and Key panel.
124
+ Human-readable name shown in the LayersMenu panel and Key panel.
138
125
 
139
126
  ---
140
127
 
@@ -142,15 +129,61 @@ Human-readable name shown in the Layers panel and Key panel.
142
129
 
143
130
  **Type:** `string | GeoJSON.FeatureCollection`
144
131
 
145
- GeoJSON source. Provide a URL string for remote data, or a GeoJSON object for inline data. Use alongside `transformRequest` to add authentication or append bbox parameters to the request.
132
+ GeoJSON source. Provide a URL string for remote data, or a `FeatureCollection` object for inline data.
133
+
134
+ For data that needs authentication headers or viewport-based filtering, use `dynamicGeoJSON` instead.
135
+
136
+ ---
137
+
138
+ ### `dynamicGeoJSON`
139
+
140
+ **Type:** `Object`
141
+
142
+ Enables dynamic, bbox-aware GeoJSON fetching — the plugin calls your API as the map pans and zooms, loading features for the current viewport and evicting distant ones. Configure this instead of `geojson` when your data is too large to load all at once.
143
+
144
+ | Property | Type | Description |
145
+ |----------|------|-------------|
146
+ | `url` | `string` | **Required.** Base URL for the GeoJSON API endpoint |
147
+ | `idProperty` | `string` | **Required.** Property name that uniquely identifies each feature. Used for deduplication across viewport fetches |
148
+ | `transformRequest` | `Function` | Called before each fetch. Return a URL string or `{ url, headers }` object to add auth headers or modify the URL |
149
+ | `maxFeatures` | `number` | Optional. Cap on features held in memory across all viewport fetches. Older out-of-viewport features are evicted when exceeded |
150
+
151
+ **`transformRequest` signature:** `transformRequest(url, { bbox, zoom, dataset })`
152
+
153
+ | Argument | Type | Description |
154
+ |----------|------|-------------|
155
+ | `url` | `string` | The base URL |
156
+ | `bbox` | `number[]` | Current viewport bounds as `[west, south, east, north]` |
157
+ | `zoom` | `number` | Current map zoom level |
158
+ | `dataset` | `Object` | The full dataset configuration |
159
+
160
+ ```js
161
+ {
162
+ id: 'land-parcels',
163
+ dynamicGeoJSON: {
164
+ url: 'https://example.com/api/parcels',
165
+ idProperty: 'parcel_id',
166
+ transformRequest: (url, { bbox }) => {
167
+ const separator = url.includes('?') ? '&' : '?'
168
+ return {
169
+ url: `${url}${separator}bbox=${bbox.join(',')}`,
170
+ headers: { Authorization: `Bearer ${getToken()}` }
171
+ }
172
+ },
173
+ maxFeatures: 50000
174
+ },
175
+ minZoom: 10,
176
+ style: { stroke: '#d4351c', strokeWidth: 2 }
177
+ }
178
+ ```
146
179
 
147
180
  ---
148
181
 
149
182
  ### `tiles`
150
183
 
151
- **Type:** `string[]`
184
+ **Type:** `string | string[]`
152
185
 
153
- Array of vector tile URL templates (e.g. `https://example.com/tiles/{z}/{x}/{y}`). When set, the dataset uses a vector tile source instead of GeoJSON.
186
+ Vector tile URL template or array of templates (e.g. `'https://example.com/tiles/{z}/{x}/{y}'`). When set, the dataset uses a vector tile source instead of GeoJSON.
154
187
 
155
188
  ---
156
189
 
@@ -162,55 +195,44 @@ The layer name within the vector tile source to render. Required when using `til
162
195
 
163
196
  ---
164
197
 
165
- ### `transformRequest`
166
-
167
- **Type:** `Function`
198
+ ### `idProperty`
168
199
 
169
- A function called before each fetch to transform the request. Its primary purpose is to attach authentication credentials — API keys, OAuth tokens, or other headers. It also receives the current viewport context so you can append bbox or zoom parameters to the URL if your API supports spatial filtering.
200
+ **Type:** `string`
170
201
 
171
- The plugin handles all dynamic fetching concerns (viewport tracking, debouncing, deduplication, caching, request cancellation) `transformRequest` only needs to return the final URL and any headers.
202
+ Property name used to uniquely identify features in a static `geojson` source. When set, the plugin promotes this property to the MapLibre feature ID (`promoteId`) so that feature IDs are stable and derived from your data rather than auto-generated.
172
203
 
173
- **Signature:** `transformRequest(url, { bbox, zoom, dataset })`
204
+ Required for `setFeatureVisibility` to work correctly the IDs you pass must match the values of this property in your data.
174
205
 
175
- | Argument | Type | Description |
176
- |----------|------|-------------|
177
- | `url` | `string` | The base URL from `geojson` |
178
- | `bbox` | `number[]` | Current viewport bounds as `[west, south, east, north]` |
179
- | `zoom` | `number` | Current map zoom level |
180
- | `dataset` | `Object` | The full dataset configuration |
181
-
182
- Return either a plain URL string or an object `{ url, headers }`. The object form is needed when attaching auth headers.
206
+ > [!NOTE]
207
+ > For `dynamicGeoJSON` sources, set `idProperty` inside the `dynamicGeoJSON` object, not here.
183
208
 
184
209
  ```js
185
- // Auth headers only (no bbox filtering)
186
- transformRequest: (url) => ({
187
- url,
188
- headers: { Authorization: `Bearer ${getToken()}` }
189
- })
190
-
191
- // Append bbox to URL for server-side spatial filtering
192
- transformRequest: (url, { bbox }) => {
193
- const separator = url.includes('?') ? '&' : '?'
194
- return { url: `${url}${separator}bbox=${bbox.join(',')}` }
195
- }
196
-
197
- // Both — auth + bbox
198
- transformRequest: (url, { bbox }) => {
199
- const separator = url.includes('?') ? '&' : '?'
200
- return {
201
- url: `${url}${separator}bbox=${bbox.join(',')}`,
202
- headers: { Authorization: `Bearer ${getToken()}` }
203
- }
210
+ // Features have { properties: { parcel_id: 'ABC123', ... } }
211
+ {
212
+ id: 'my-parcels',
213
+ geojson: 'https://example.com/api/parcels',
214
+ idProperty: 'parcel_id'
204
215
  }
205
216
  ```
206
217
 
207
218
  ---
208
219
 
209
- ### `idProperty`
220
+ ### `generateIds`
210
221
 
211
- **Type:** `string`
222
+ **Type:** `boolean`
223
+
224
+ When `true`, MapLibre auto-generates integer IDs for GeoJSON features by their array index position (0-based). Use this when your features have no natural unique ID property and you need `setFeatureVisibility` to work.
225
+
226
+ > [!NOTE]
227
+ > Auto-generated IDs are positional and reset on every `setData` call. If your data changes between calls, the same integer ID may refer to a different feature. Prefer `idProperty` whenever your data has a stable unique field.
212
228
 
213
- Property name used to uniquely identify features. Required alongside `transformRequest` to enable dynamic bbox-based fetching — the plugin uses it internally to deduplicate features across successive viewport fetches.
229
+ ```js
230
+ {
231
+ id: 'my-parcels',
232
+ geojson: 'https://example.com/api/parcels',
233
+ generateIds: true
234
+ }
235
+ ```
214
236
 
215
237
  ---
216
238
 
@@ -244,18 +266,10 @@ Maximum zoom level at which the dataset is visible.
244
266
 
245
267
  ---
246
268
 
247
- ### `maxFeatures`
248
-
249
- **Type:** `number`
269
+ ### `visible`
250
270
 
251
- Only applies to dynamic sources (those using `transformRequest`). Caps the number of features held in memory across all viewport fetches — older out-of-viewport features are evicted when the limit is exceeded. Omit for small or bounded datasets; set it when users are likely to pan extensively over a large dataset.
252
-
253
- ---
254
-
255
- ### `visibility`
256
-
257
- **Type:** `'visible' | 'hidden'`
258
- **Default:** `'visible'`
271
+ **Type:** `boolean`
272
+ **Default:** `true`
259
273
 
260
274
  Initial visibility of the dataset.
261
275
 
@@ -266,7 +280,7 @@ Initial visibility of the dataset.
266
280
  **Type:** `boolean`
267
281
  **Default:** `false`
268
282
 
269
- When `true`, the dataset appears in the Key panel with its style symbol and label.
283
+ When `true`, the dataset appears in the Key panel with its style symbol and label. Sublayers inherit this value — set `showInKey: false` on an individual sublayer to opt it out.
270
284
 
271
285
  ---
272
286
 
@@ -275,7 +289,7 @@ When `true`, the dataset appears in the Key panel with its style symbol and labe
275
289
  **Type:** `boolean`
276
290
  **Default:** `false`
277
291
 
278
- When `true`, the dataset appears in the Layers panel and can be toggled on and off by the user.
292
+ When `true`, the dataset appears in the LayersMenu panel and can be toggled on and off by the user. Sublayers inherit this value — set `showInMenu: false` on an individual sublayer to opt it out.
279
293
 
280
294
  ---
281
295
 
@@ -283,7 +297,7 @@ When `true`, the dataset appears in the Layers panel and can be toggled on and o
283
297
 
284
298
  **Type:** `string`
285
299
 
286
- Groups this dataset with others sharing the same `groupLabel` in the Layers panel, rendering them as a single collapsible group.
300
+ Groups this dataset with others sharing the same `groupLabel` in the LayersMenu panel, rendering them as a single collapsible group.
287
301
 
288
302
  ---
289
303
 
@@ -380,80 +394,81 @@ style: {
380
394
 
381
395
  Array of sublayer rules that partition the dataset into visually distinct groups based on feature filters. Each sublayer is rendered as a separate map layer.
382
396
 
383
- Sublayers inherit the parent dataset's style and only override what they specify in their own `style` object. For polygon/line datasets, fill precedence is (highest to lowest): sublayer `fillPattern` sublayer `fill` parent `fillPattern` → parent `fill`. For symbol datasets, each symbol property is inherited individually from the parent unless the sublayer sets it explicitly.
397
+ Sublayer styles merge over the parent's the sublayer wins on any property it sets. Rendering type is driven by the merged result: `symbol` > `fillPattern`/`fill` > `stroke`.
384
398
 
385
399
  #### `Sublayer` properties
386
400
 
387
401
  | Property | Type | Description |
388
402
  |----------|------|-------------|
389
403
  | `id` | `string` | **Required.** Unique identifier within the dataset |
390
- | `label` | `string` | Human-readable name shown in the Layers and Key panels |
404
+ | `label` | `string` | Human-readable name shown in the LayersMenu and Key panels |
391
405
  | `filter` | `FilterExpression` | MapLibre filter expression to match features for this sublayer |
392
406
  | `style` | `Object` | Style overrides. Accepts the same properties as the dataset `style` object |
393
- | `showInKey` | `boolean` | Shows this sublayer in the Key panel. Inherits from dataset if not set |
394
- | `showInMenu` | `boolean` | Shows this sublayer in the Layers panel. **Default:** `false` |
407
+ | `showInKey` | `boolean` | Shows this sublayer in the Key panel. Inherits from the dataset when not set; explicit `false` overrides a dataset-level `true` |
408
+ | `showInMenu` | `boolean` | Shows this sublayer in the LayersMenu panel. Inherits from the dataset when not set; explicit `false` overrides a dataset-level `true` |
395
409
 
396
410
  **Polygon/line example:**
397
411
 
398
412
  ```js
399
- sublayers: [
400
- {
401
- id: 'active',
402
- label: 'Active parcels',
403
- filter: ['==', ['get', 'status'], 'active'],
404
- showInMenu: true,
405
- style: {
406
- stroke: '#00703c',
407
- fill: 'rgba(0,112,60,0.1)',
408
- symbolDescription: 'Green outline'
409
- }
410
- },
411
- {
412
- id: 'inactive',
413
- label: 'Inactive parcels',
414
- filter: ['==', ['get', 'status'], 'inactive'],
415
- showInMenu: true,
416
- style: {
417
- stroke: '#d4351c',
418
- fillPattern: 'diagonal-cross-hatch',
419
- fillPatternForegroundColor: '#d4351c'
413
+ {
414
+ id: 'field-parcels',
415
+ label: 'Field parcels',
416
+ geojson: parcelsData,
417
+ showInKey: true,
418
+ showInMenu: true,
419
+ sublayers: [
420
+ {
421
+ id: 'active',
422
+ label: 'Active parcels',
423
+ filter: ['==', ['get', 'status'], 'active'],
424
+ style: {
425
+ stroke: '#00703c',
426
+ fill: 'rgba(0,112,60,0.1)',
427
+ symbolDescription: 'Green outline'
428
+ }
429
+ },
430
+ {
431
+ id: 'inactive',
432
+ label: 'Inactive parcels',
433
+ filter: ['==', ['get', 'status'], 'inactive'],
434
+ style: {
435
+ stroke: '#d4351c',
436
+ fillPattern: 'diagonal-cross-hatch',
437
+ fillPatternForegroundColor: '#d4351c'
438
+ }
420
439
  }
421
- }
422
- ]
440
+ ]
441
+ }
423
442
  ```
424
443
 
425
444
  **Symbol (point) example — scheduled monuments by type:**
426
445
 
427
- When the parent dataset has `symbol` set, each sublayer can override individual symbol properties to represent different categories. Properties not set on the sublayer are inherited from the parent.
446
+ Here the parent defines the shared symbol shape; each sublayer only overrides what differs.
428
447
 
429
448
  ```js
430
449
  {
431
450
  id: 'scheduled-monuments',
432
451
  geojson: scheduledMonumentsData,
452
+ showInKey: true,
453
+ showInMenu: true,
433
454
  style: { symbol: 'square' },
434
455
  sublayers: [
435
456
  {
436
457
  id: 'prehistoric',
437
458
  label: 'Prehistoric sites',
438
459
  filter: ['==', ['get', 'type'], 'prehistoric'],
439
- showInKey: true,
440
- showInMenu: true,
441
460
  style: { symbolBackgroundColor: '#0f7a52' }
442
461
  },
443
462
  {
444
463
  id: 'roman',
445
464
  label: 'Roman sites',
446
465
  filter: ['==', ['get', 'type'], 'roman'],
447
- showInKey: true,
448
- showInMenu: true,
449
466
  style: { symbolBackgroundColor: '#54319f' }
450
467
  },
451
468
  {
452
469
  id: 'medieval',
453
470
  label: 'Medieval sites',
454
471
  filter: ['==', ['get', 'type'], 'medieval'],
455
- showInKey: true,
456
- showInMenu: true,
457
472
  style: { symbolBackgroundColor: '#ca357c' }
458
473
  }
459
474
  ]
@@ -533,26 +548,26 @@ datasetsPlugin.setDatasetVisibility(false, { datasetId: 'my-parcels', sublayerId
533
548
 
534
549
  ### `setFeatureVisibility(visible, featureIds, scope)`
535
550
 
536
- Show or hide specific features within a dataset without removing them from the source.
551
+ Show or hide specific features within a dataset without removing them from the source. The feature IDs you pass are matched against the dataset's `idProperty` value, or against the native feature `id` when `idProperty` is not set.
552
+
553
+ > [!NOTE]
554
+ > The dataset must have `idProperty` or `generateIds: true` configured for feature matching to work. A console warning is emitted if neither is set.
537
555
 
538
556
  | Argument | Type | Description |
539
557
  |----------|------|-------------|
540
558
  | `visible` | `boolean` | `true` to show, `false` to hide |
541
- | `featureIds` | `(string \| number)[]` | IDs of the features to target |
559
+ | `featureIds` | `(string \| number)[]` | IDs of the features to target — must match the `idProperty` values in your data |
542
560
  | `scope.datasetId` | `string` | ID of the dataset |
543
- | `scope.idProperty` | `string \| null` | Property name to match features on. Pass `null` to match against the top-level `feature.id` |
544
561
 
545
562
  ```js
546
- // Hide by a feature property
547
- datasetsPlugin.setFeatureVisibility(false, [123, 456], {
548
- datasetId: 'my-parcels',
549
- idProperty: 'parcel_id'
563
+ // Dataset configured with idProperty: 'parcel_id'
564
+ datasetsPlugin.setFeatureVisibility(false, ['ABC123', 'DEF456'], {
565
+ datasetId: 'my-parcels'
550
566
  })
551
567
 
552
- // Show using feature.id
553
- datasetsPlugin.setFeatureVisibility(true, [123, 456], {
554
- datasetId: 'my-parcels',
555
- idProperty: null
568
+ // Show previously hidden features
569
+ datasetsPlugin.setFeatureVisibility(true, ['ABC123'], {
570
+ datasetId: 'my-parcels'
556
571
  })
557
572
  ```
558
573
 
@@ -674,6 +689,26 @@ datasetsPlugin.setData(
674
689
 
675
690
  ---
676
691
 
692
+ ### `setGlobals(values)`
693
+
694
+ Set global state that applies across all datasets. Currently supports `opacityMode`.
695
+
696
+ | Argument | Type | Description |
697
+ |----------|------|-------------|
698
+ | `values.opacityMode` | `'dataset' \| 'global' \| 'multiply'` | Controls how opacity values are combined when both a global opacity and a per-dataset opacity are set |
699
+
700
+ | Mode | Behaviour |
701
+ |------|-----------|
702
+ | `'dataset'` | Each dataset uses its own `style.opacity` only. Global opacity is ignored |
703
+ | `'global'` | All datasets use the global opacity, ignoring per-dataset values |
704
+ | `'multiply'` | Effective opacity is `globalOpacity × datasetOpacity` |
705
+
706
+ ```js
707
+ datasetsPlugin.setGlobals({ opacityMode: 'multiply' })
708
+ ```
709
+
710
+ ---
711
+
677
712
  ## Events
678
713
 
679
714
  Subscribe to events using `interactiveMap.on()`.
@@ -295,7 +295,6 @@ Emitted when the user confirms their selection (clicks "Done").
295
295
 
296
296
  // If features were selected:
297
297
  selectedFeatures: [...],
298
- selectionBounds: [west, south, east, north],
299
298
 
300
299
  // If markers were selected:
301
300
  selectedMarkers: ['...']
@@ -340,10 +339,9 @@ Emitted whenever the selected features or selected markers change.
340
339
  ```js
341
340
  {
342
341
  selectedFeatures: [
343
- { featureId: '...', layerId: '...', properties: {...}, geometry: {...} }
342
+ { featureId: '...', layerId: '...', idProperty: '...', properties: {...} }
344
343
  ],
345
344
  selectedMarkers: ['...'], // array of selected marker IDs
346
- selectionBounds: [west, south, east, north] | null,
347
345
  contiguous: boolean // true when 2+ features are selected and all form a single contiguous group
348
346
  }
349
347
  ```
@@ -351,7 +349,6 @@ Emitted whenever the selected features or selected markers change.
351
349
  ```js
352
350
  interactiveMap.on('interact:selectionchange', (e) => {
353
351
  console.log('Selected features:', e.selectedFeatures)
354
- console.log('Bounds:', e.selectionBounds)
355
352
  })
356
353
  ```
357
354
 
@@ -91,8 +91,15 @@ const config = {
91
91
  sidebar: [
92
92
  { text: 'Basic map', href: '/examples/basic-map' },
93
93
  { text: 'Button-triggered map', href: '/examples/button-map' },
94
- { text: 'Add a marker with a panel', href: '/examples/add-marker-with-panel' },
95
- { text: 'Toggle marker label on click', href: '/examples/toggle-marker-label' },
94
+ { text: 'Map with marker and panel', href: '/examples/add-marker-with-panel' },
95
+ { text: 'Toggle marker label', href: '/examples/toggle-marker-label' },
96
+ { text: 'Place a marker to continue', href: '/examples/place-marker' },
97
+ { text: 'Add a search control', href: '/examples/search-control' },
98
+ { text: 'Select a feature', href: '/examples/select-feature' },
99
+ { text: 'Change map style', href: '/examples/style-switcher' },
100
+ { text: 'Draw tools', href: '/examples/draw-tools' },
101
+ { text: 'Add symbols', href: '/examples/add-symbols' },
102
+ { text: 'Add polygons', href: '/examples/add-polygons' },
96
103
  ],
97
104
  },
98
105
  {
@@ -1,8 +1,58 @@
1
1
  {
2
2
  "templates": [
3
3
  {
4
- "name": "Map page",
5
- "path": "/assets/templates/map.njk",
4
+ "name": "Basic map",
5
+ "path": "/assets/templates/basic-map.njk",
6
+ "type": "nunjucks"
7
+ },
8
+ {
9
+ "name": "Map with marker and panel",
10
+ "path": "/assets/templates/marker-panel.njk",
11
+ "type": "nunjucks"
12
+ },
13
+ {
14
+ "name": "Button-triggered map",
15
+ "path": "/assets/templates/button-map.njk",
16
+ "type": "nunjucks"
17
+ },
18
+ {
19
+ "name": "Toggle marker label",
20
+ "path": "/assets/templates/toggle-marker-label.njk",
21
+ "type": "nunjucks"
22
+ },
23
+ {
24
+ "name": "Place a marker to continue",
25
+ "path": "/assets/templates/place-marker.njk",
26
+ "type": "nunjucks"
27
+ },
28
+ {
29
+ "name": "Add a search control",
30
+ "path": "/assets/templates/search-control.njk",
31
+ "type": "nunjucks"
32
+ },
33
+ {
34
+ "name": "Select a feature",
35
+ "path": "/assets/templates/select-feature.njk",
36
+ "type": "nunjucks"
37
+ },
38
+ {
39
+ "name": "Change map style",
40
+ "path": "/assets/templates/style-switcher.njk",
41
+ "type": "nunjucks"
42
+ },
43
+ {
44
+ "name": "Draw tools",
45
+ "path": "/assets/templates/draw-tools.njk",
46
+ "type": "nunjucks"
47
+ },
48
+ {
49
+ "name": "Add symbols",
50
+ "path": "/assets/templates/add-symbols.njk",
51
+ "type": "nunjucks"
52
+ },
53
+ {
54
+ "name": "Add polygons",
55
+ "path": "/assets/templates/add-polygons.njk",
6
56
  "type": "nunjucks"
7
57
  }
8
58
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defra/interactive-map",
3
- "version": "0.0.30-alpha",
3
+ "version": "0.0.32-alpha",
4
4
  "description": "An accessible map component",
5
5
  "repository": {
6
6
  "type": "git",
@@ -93,8 +93,7 @@
93
93
  .im-c-datasets-layers-group .im-c-datasets-layers__item:not(:last-child) {
94
94
  margin-bottom: 0;
95
95
  }
96
-
97
- .im-c-datasets-layers__item-label {
96
+ .im-c-datasets-layers__item .im-c-datasets-layers__item-label {
98
97
  width: 100%;
99
98
  max-width: none;
100
99
  align-items: start;
@@ -133,6 +132,10 @@
133
132
  padding-top: 0;
134
133
  }
135
134
 
135
+ .im-c-datasets-layers .govuk-checkboxes__input[aria-disabled=true] + .govuk-checkboxes__label {
136
+ opacity: 0.5;
137
+ }
138
+
136
139
  .im-c-datasets {
137
140
  display: block;
138
141
  }
@@ -0,0 +1 @@
1
+ import t from"@babel/runtime/helpers/asyncToGenerator";import e from"@babel/runtime/helpers/defineProperty";import{g as r,a as i,D as a,h as s,l as o,d as l}from"./im-datasets-plugin.js";import"preact/compat";import"preact/jsx-runtime";function y(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);e&&(i=i.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),r.push.apply(r,i)}return r}var n=(t,r,a)=>{var{hasStroke:s,strokeLayerId:o}=r;if(s&&!t.getLayer(o)){var l=function(t){for(var r=1;r<arguments.length;r++){var i=null!=arguments[r]?arguments[r]:{};r%2?y(Object(i),!0).forEach(function(r){e(t,r,i[r])}):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(i)):y(Object(i)).forEach(function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(i,e))})}return t}({"line-color":i(r.style.stroke,a),"line-width":r.style.strokeWidth||1,"line-opacity":r.opacity},r.style.strokeDashArray?{"line-dasharray":r.style.strokeDashArray}:{}),n=r.getStrokeSource(l);t.addLayer(n)}},h=(t,e,a,s,o,l)=>{var y,{sourceId:d,source:p}=e;p&&!t.getSource(d)&&t.addSource(d,p);var u=a.id;return((t,e,i,a,s)=>{var{hasSymbol:o,symbolLayerId:l}=e;if(o&&a&&l&&!t.getLayer(l)){var y=a.getSymbolDef(e.style);if(y){var n=a.getSymbolImageId(e.style,i,!1,s);if(n){var h=r(e.style,y);t.addLayer(e.getSymbolSource(n,h,y))}}}})(t,e,a,s,l),function(t,e,r,a){var s=arguments.length>4&&void 0!==arguments[4]?arguments[4]:1,{hasFill:o,fillLayerId:l}=e;if(o&&l&&!t.getLayer(l)){var y=a.getPatternImageId(e.style,r,s),n=y?{"fill-pattern":y,"fill-opacity":e.opacity}:{"fill-color":i(e.style.fill,r),"fill-opacity":e.opacity};t.addLayer(e.getFillSource(n))}}(t,e,u,o,l),n(t,e,u),null!==(y=e.sublayers)&&void 0!==y&&y.length?(e.sublayers.forEach(e=>{h(t,e,a,s,o,l)}),d):e.isSublayer?void 0:d},d=t=>{var[e,r]=t,i=(t=>t<=.25?"left":t>=.75?"right":"")(e),a=(t=>t<=.25?"top":t>=.75?"bottom":"")(r);return a+(i&&a?"-":"")+i||"center"};function p(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);e&&(i=i.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),r.push.apply(r,i)}return r}function u(t){for(var r=1;r<arguments.length;r++){var i=null!=arguments[r]?arguments[r]:{};r%2?p(Object(i),!0).forEach(function(r){e(t,r,i[r])}):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(i)):p(Object(i)).forEach(function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(i,e))})}return t}class c extends a{get visibility(){return this.visible?"visible":"none"}get fillLayerId(){return this.hasSublayers||this.hasSymbol?null:this.hasFill?this.id:null}get strokeLayerId(){return this.hasSublayers||this.hasSymbol?null:this.hasStroke?this.hasFill?"".concat(this.id,"-stroke"):this.id:null}get symbolLayerId(){return this.hasSublayers?null:this.hasSymbol?this.id:null}get layerIds(){return this.hasSublayers?this.sublayers.flatMap(t=>t.layerIds).filter(Boolean):[this.symbolLayerId,this.fillLayerId,this.strokeLayerId].filter(Boolean)}getLayersWithValue(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],r=[];if(!1===e||this[e]){var i=[this.symbolLayerId,this.fillLayerId,this.strokeLayerId].filter(Boolean);if(i.length){var a=this[t];r.push({layerIds:i,[t]:a})}}return this.hasSublayers&&this.sublayers.forEach(i=>{(!1===e||i[e])&&r.push(i.getLayersWithValue(t)[0])}),r}getLayersWithVisibility(){return this.getLayersWithValue("visibility")}getLayersWithOpacity(){return this.getLayersWithValue("opacity")}getLayersWithFilters(){return this.getLayersWithValue("filter","hasHiddenFeatures")}get sourceId(){if(this.isSublayer)return this.parent.sourceId;if(this.hasDynamicGeoJSON)return this.dynamicGeoJSON.sourceId;if(this.tiles){var t=Array.isArray(this.tiles)?this.tiles.join(","):this.tiles;return"tiles-".concat(s(t))}return this.geojson?"string"==typeof this.geojson?"geojson-".concat(s(this.geojson)):"geojson-".concat(this.id):"source-".concat(this.id)}_geojsonIdStrategy(){var t;return this.idProperty?{promoteId:this.idProperty}:this.generateIds?{generateId:!0}:(null!==(t=this.geojson)&&void 0!==t&&null!==(t=t.features)&&void 0!==t&&t.some(t=>"string"==typeof t.id)&&o.warn('Dataset "'.concat(this.id,'" has GeoJSON features with string native IDs. MapLibre only surfaces integer native feature IDs through queryRenderedFeatures. Use idProperty to promote a string property instead.')),{})}get source(){if(this.hasDynamicGeoJSON)return this.dynamicGeoJSON.source;if(this.tiles){var t={type:"vector",tiles:this.tiles,minzoom:this.minZoom||0,maxzoom:this.maxZoom||22};return this.idProperty&&this.sourceLayer&&(t.promoteId={[this.sourceLayer]:this.idProperty}),t}return this.geojson?u({type:"geojson",data:this.geojson},this._geojsonIdStrategy()):null}getSymbolSource(t,e,r){return u({id:this.symbolLayerId,type:"symbol",source:this.sourceId,"source-layer":this.sourceLayer,minzoom:this.minZoom,maxzoom:this.maxZoom,layout:{visibility:this.visibility,"icon-image":t,"icon-anchor":d(e||(null==r?void 0:r.anchor)||[.5,.5]),"icon-allow-overlap":!0}},this.filter?{filter:this.filter}:{})}getFillSource(t){return u({id:this.fillLayerId,type:"fill",source:this.sourceId,"source-layer":this.sourceLayer,minzoom:this.minZoom,maxzoom:this.maxZoom,layout:{visibility:this.visibility},paint:t},this.filter?{filter:this.filter}:{})}getStrokeSource(t){return u({id:this.strokeLayerId,type:"line",source:this.sourceId,"source-layer":this.sourceLayer,minzoom:this.minZoom,maxzoom:this.maxZoom,layout:{visibility:this.visibility},paint:t},this.filter?{filter:this.filter}:{})}get _hiddenFeaturesIdExpression(){return this.hasDynamicGeoJSON?this.dynamicGeoJSON.hiddenFeaturesIdExpression:this.idProperty?["to-string",["get",this.idProperty]]:["to-string",["id"]]}get _hiddenFeaturesFilter(){var t,e=null===(t=this.hiddenFeatures)||void 0===t?void 0:t.filter(t=>-1!==t);return null!=e&&e.length?["!",["in",this._hiddenFeaturesIdExpression,["literal",e.map(String)]]]:null}get filter(){var t,e=["all"];null!==(t=this.parent)&&void 0!==t&&t.filter&&e.push(this.parent.filter),this._datasetDefinition.filter&&e.push(this._datasetDefinition.filter);var r=this._hiddenFeaturesFilter;return r&&e.push(r),1===e.length?null:e.length>2?e:e[1]}}class m{constructor(t,e,r){this._mapProvider=t,this._map=t.map,this._symbolRegistry=e,this._patternRegistry=r,this._datasetSourceMap=new Map,window._datasetSourceMap=this._datasetSourceMap,this._symbolLayerIds=new Set}createDataset(t){return new c(t)}init(e){var r=this;return t(function*(){var{patternConfigs:t,symbolConfigs:i}=l.getPatternAndSymbolConfigs();yield r.addPatternsAndSymbolsToMap(t,i,e),r._symbolLayerIds.clear(),l.forEachDataset(t=>r._addLayers(t,e)),yield new Promise(t=>r._map.once("idle",t))})()}removeLayer(t){this._map.getLayer(t)&&this._map.removeLayer(t),this._symbolLayerIds.delete(t)}addPatternsAndSymbolsToMap(e,r,i){var a=this;return t(function*(){var t=i.id;return Promise.all([a._mapProvider.addPatternsToMap(e,t,a._patternRegistry),a._mapProvider.addSymbolsToMap(r,i,a._symbolRegistry)])})()}destroy(){var t=new Set;l.forEachDataset(e=>{var r=e.sourceId;this._getLayersUsingSource(r).forEach(t=>this.removeLayer(t)),!t.has(r)&&this._map.getSource(r)&&(this._map.removeSource(r),t.add(r))}),this._datasetSourceMap.clear()}onMapStyleChange(e,r){var i=this;return t(function*(){yield new Promise(t=>i._map.once("idle",t));var{patternConfigs:t,symbolConfigs:a}=l.getPatternAndSymbolConfigs();yield i.addPatternsAndSymbolsToMap(t,a,e),i._symbolLayerIds.clear(),l.forEachDataset(t=>{i._addLayers(t,e),i._applyFeatureFilter(t)}),r.forEach(t=>t.reapply())})()}onMapSizeChange(e){var r=this;return t(function*(){var{patternConfigs:t,symbolConfigs:i}=l.getPatternAndSymbolConfigs();yield r.addPatternsAndSymbolsToMap(t,i,e),l.forEach(t=>{var{fillLayerId:i,symbolLayerId:a}=t;if(a&&r._symbolLayerIds.has(a)&&r._map.getLayer(a)){var s=r._symbolRegistry.getSymbolImageId(t.style,e,!1,r._pixelRatio);s&&r._map.setLayoutProperty(a,"icon-image",s)}else if(i&&r._map.getLayer(i)){var o=r._patternRegistry.getPatternImageId(t.style,e.id,r._pixelRatio);o&&r._map.setPaintProperty(i,"fill-pattern",o)}})})()}addDataset(e,r){var i=this;return t(function*(){var t=l.getDataset(e);yield i.addPatternsAndSymbolsToMap(t.patternConfigs,t.symbolConfigs,r),i._addLayers(t,r)})()}removeDataset(t){var e=l.getDataset(t);if(e){var{sourceId:r,layerIds:i}=e;i.forEach(t=>this.removeLayer(t));var a=l.topLevelDatasets().filter(e=>e.id!==t&&e.sourceId===r).length>0;!a&&this._map.getSource(r)&&this._map.removeSource(r),this._datasetSourceMap.delete(t)}}applyFeatureFilter(t){var e=l.getDataset(t);e&&this._applyFeatureFilter(e)}applyStyle(e,r){var i=this;return t(function*(){var t=l.getDataset(e);t.layerIds.forEach(t=>i.removeLayer(t)),yield i.addPatternsAndSymbolsToMap(t.patternConfigs,t.symbolConfigs,r),i._addLayers(t,r)})()}applyDatasetOpacity(t){var e=l.getDataset(t);e&&this._applyRegistryDatasetOpacity(e)}_applyRegistryDatasetOpacity(t){t.getLayersWithOpacity().forEach(t=>{var{layerIds:e,opacity:r}=t;e.forEach(t=>this._setPaintOpacity(t,r))})}applyGlobalOpacity(){l.forEachDataset(t=>this._applyRegistryDatasetOpacity(t))}setData(t,e){var r=this._datasetSourceMap.get(t);if(r){var i=this._map.getSource(r);i&&"function"==typeof i.setData&&i.setData(e)}}get _pixelRatio(){return this._mapProvider.map.getPixelRatio()}_addLayers(t,e){var r=h(this._map,t,e,this._symbolRegistry,this._patternRegistry,this._pixelRatio);this._datasetSourceMap.set(t.id,r),this._maintainSymbolOrdering(t)}_getFirstSymbolLayerId(){var t,e=this._map.getStyle();if(null==e||!e.layers)return null;var r=e.layers.find(t=>this._symbolLayerIds.has(t.id));return null!==(t=null==r?void 0:r.id)&&void 0!==t?t:null}_maintainSymbolOrdering(t){var e=(t=t.isSublayer?t.parent:t).layerIds.filter(t=>t&&this._map.getLayer(t));e.forEach(t=>{var e;"symbol"===(null===(e=this._map.getLayer(t))||void 0===e?void 0:e.type)?this._symbolLayerIds.add(t):this._symbolLayerIds.delete(t)});var r=this._getFirstSymbolLayerId();r&&e.forEach(t=>{this._symbolLayerIds.has(t)||this._map.moveLayer(t,r)})}applyDatasetVisibility(t){var e=l.getDataset(t);e&&this._applyRegistryDatasetVisibility(e)}_applyRegistryDatasetVisibility(t){t.getLayersWithVisibility().forEach(t=>{var{layerIds:e,visibility:r}=t;e.forEach(t=>{this._map.getLayer(t)&&this._map.setLayoutProperty(t,"visibility",r)})})}applyGlobalVisibility(){l.forEachDataset(t=>this._applyRegistryDatasetVisibility(t))}_applyFeatureFilter(t){t.getLayersWithFilters().forEach(t=>{var{layerIds:e,filter:r}=t;e.forEach(t=>{this._map.getLayer(t)&&this._map.setFilter(t,r)})})}_setPaintOpacity(t,e){var r=this._map.getLayer(t);if(r){var i={line:"line-opacity",symbol:"icon-opacity"}[r.type]||"fill-opacity";this._map.setPaintProperty(t,i,e)}}_getLayersUsingSource(t){var e=this._map.getStyle();return null!=e&&e.layers?e.layers.filter(e=>e.source===t).map(t=>t.id):[]}}export{m as default};