@defra/interactive-map 0.0.19-alpha → 0.0.21-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 (57) hide show
  1. package/README.md +1 -1
  2. package/dist/esm/im-shell.js +1 -1
  3. package/dist/umd/index.js +1 -1
  4. package/docs/api/button-definition.md +22 -5
  5. package/docs/api/map-style-config.md +2 -11
  6. package/docs/api/marker-config.md +19 -5
  7. package/docs/api.md +75 -46
  8. package/docs/architecture.md +0 -2
  9. package/{assets → docs/assets}/css/docusaurus.css +78 -1
  10. package/docs/assets/images/basic-map.jpg +0 -0
  11. package/docs/assets/images/button-first.jpg +0 -0
  12. package/{assets → docs/assets}/images/hero.png +0 -0
  13. package/docs/assets/images/marker-panel.jpg +0 -0
  14. package/docs/examples/add-marker-with-panel.mdx +112 -48
  15. package/docs/examples/basic-map.mdx +43 -14
  16. package/docs/examples/button-map.mdx +43 -14
  17. package/docs/examples/index.mdx +5 -5
  18. package/docs/getting-started.md +80 -53
  19. package/docs/plugins/datasets.md +11 -11
  20. package/docusaurus.config.cjs +5 -4
  21. package/package.json +7 -3
  22. package/plugins/beta/datasets/adapters/maplibre/dist/esm/im-datasets-ml-adapter.js +1 -0
  23. package/plugins/beta/datasets/adapters/maplibre/dist/esm/index.js +1 -0
  24. package/plugins/beta/datasets/adapters/maplibre/dist/umd/im-datasets-ml-adapter.js +2 -0
  25. package/plugins/beta/datasets/adapters/maplibre/dist/umd/im-datasets-ml-adapter.js.LICENSE.txt +1 -0
  26. package/plugins/beta/datasets/adapters/maplibre/dist/umd/index.js +1 -0
  27. package/plugins/beta/datasets/dist/esm/im-datasets-plugin.js +1 -1
  28. package/plugins/beta/datasets/dist/umd/im-datasets-plugin.js +1 -1
  29. package/plugins/beta/datasets/src/adapters/maplibre/layerBuilders.js +4 -4
  30. package/plugins/beta/datasets/src/adapters/maplibre/maplibreLayerAdapter.js +26 -7
  31. package/plugins/beta/datasets/src/defaults.js +1 -1
  32. package/plugins/beta/datasets/src/manifest.js +1 -1
  33. package/plugins/beta/datasets/src/panels/Layers.jsx +4 -4
  34. package/plugins/beta/datasets/src/utils/mergeSublayer.js +1 -1
  35. package/plugins/beta/draw-ml/dist/css/index.css +19 -2
  36. package/providers/maplibre/dist/esm/im-maplibre-provider.js +1 -1
  37. package/providers/maplibre/dist/umd/im-maplibre-framework.js +1 -1
  38. package/providers/maplibre/dist/umd/im-maplibre-framework.js.LICENSE.txt +1 -1
  39. package/providers/maplibre/dist/umd/im-maplibre-provider.js +1 -1
  40. package/providers/maplibre/src/maplibreProvider.js +5 -3
  41. package/providers/maplibre/src/maplibreProvider.test.js +44 -2
  42. package/providers/maplibre/src/utils/patternImages.js +16 -10
  43. package/providers/maplibre/src/utils/patternImages.test.js +50 -19
  44. package/rollup.esm.mjs +9 -0
  45. package/src/InteractiveMap/InteractiveMap.js +2 -2
  46. package/src/InteractiveMap/InteractiveMap.test.js +4 -4
  47. package/src/services/eventBus.js +61 -0
  48. package/src/services/eventBus.test.js +70 -0
  49. package/src/utils/patternUtils.js +8 -3
  50. package/src/utils/patternUtils.test.js +17 -0
  51. package/webpack.umd.mjs +1 -0
  52. package/docs/assets/basic-map.jpg +0 -0
  53. package/docs/assets/button-first.jpg +0 -0
  54. package/docs/assets/maker-panel.jpg +0 -0
  55. /package/docs/assets/{screens-blue.jpg → images/screens-blue.jpg} +0 -0
  56. /package/docs/assets/{screens-white.jpg → images/screens-white.jpg} +0 -0
  57. /package/{assets → docs/assets}/images/slot-map.svg +0 -0
package/docs/api.md CHANGED
@@ -27,18 +27,20 @@ Parameters:
27
27
 
28
28
  The `id` of a container element where the map will be rendered.
29
29
 
30
+ ---
31
+
30
32
  ### `options`
31
33
  **Type:** `Object`
32
34
 
33
35
  Configuration object specifying map provider, map style, behaviour, and other settings. See Options below.
34
36
 
37
+ > [!NOTE]
38
+ > In addition to the options below, any option supported by your map engine can be passed and will be forwarded to the provider constructor. See your map provider's documentation for available options (e.g., [MapLibre MapOptions](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/MapOptions/)).
39
+
35
40
  ---
36
41
 
37
42
  ## Options
38
43
 
39
- > [!NOTE]
40
- > In addition to the options below, any option supported by your map engine can be passed and will be forwarded to the provider constructor. See your map provider's documentation for available options (e.g., [MapLibre MapOptions](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/MapOptions/)).
41
-
42
44
  ---
43
45
 
44
46
  ### `appColorScheme`
@@ -47,8 +49,6 @@ Configuration object specifying map provider, map style, behaviour, and other se
47
49
 
48
50
  Colour scheme used by the application. Determines the colours of panels, buttons and controls.
49
51
 
50
- **Possible values**
51
-
52
52
  | Possible values |
53
53
  |:--|
54
54
  | **'light'** *(default)*
@@ -76,6 +76,18 @@ May be provided as:
76
76
  - A single CSS colour value applied to all map styles
77
77
  - An object keyed by map style ID, where each value is a valid CSS colour
78
78
 
79
+ ```js
80
+ // Single value applied to all map styles
81
+ new InteractiveMap('map', {
82
+ backgroundColor: '#f5f5f0'
83
+ })
84
+
85
+ // Keyed by map style ID
86
+ new InteractiveMap('map', {
87
+ backgroundColor: { outdoor: '#f5f5f0', dark: '#383F43' }
88
+ })
89
+ ```
90
+
79
91
  ---
80
92
 
81
93
  ### `behaviour`
@@ -84,16 +96,14 @@ May be provided as:
84
96
 
85
97
  Determines how and when the map is displayed.
86
98
 
87
- **Possible values**
88
-
89
99
  | Possible values |
90
100
  |:--|
91
101
  | **'buttonFirst'** *(default)*
92
- Map is initially hidden and a button is displayed in its place. Selecting the button opens the map in fullscreen mode. The optional `pageTitle` property is appended to the page title. This behaviour minimises resources downloaded when not all users need a map. |
102
+ Map is initially hidden and a button is displayed in its place. Selecting the button opens the map in fullscreen mode. The optional `pageTitle` property is appended to the page title. This provides a less intrusive experience for users who do not need or cannot use the map. It also minimises resources downloaded for services where the map is not central. |
93
103
  | **'inline'**
94
104
  The map is rendered inline with the body content and initially visible. |
95
105
  | **'hybrid'**
96
- A combination of button and inline behaviour, controlled by the optional `hybridWidth`. At smaller sizes a button is displayed; at larger sizes the map is rendered inline. When fullscreen, the optional `pageTitle` property is appended to the page title. |
106
+ A combination of buttonFirst and inline behaviour, controlled by the optional `hybridWidth`. At smaller sizes a button is displayed; at larger sizes the map is rendered inline. When fullscreen, the optional `pageTitle` property is appended to the page title. |
97
107
  | **'mapOnly'**
98
108
  Renders the map fullscreen on all devices, using the existing page title. |
99
109
 
@@ -129,7 +139,7 @@ The button is only displayed when the `behaviour` is `hybrid` or `buttonFirst`.
129
139
  ### `center`
130
140
  **Type:** `[number, number]`
131
141
 
132
- Initial center [lng, lat] or [easting, northing] depending on the crs of the map provider.
142
+ Initial centre [lng, lat] or [easting, northing] depending on the crs of the map provider.
133
143
 
134
144
  Passed directly to the underlying map engine.
135
145
 
@@ -139,7 +149,7 @@ Passed directly to the underlying map engine.
139
149
  **Type:** `string`
140
150
  **Default:** `'600px'`
141
151
 
142
- CSS height applied to the map container when the map is `inline`.
152
+ CSS height applied to the map container. Only used when the map is rendered inline; ignored when displayed fullscreen.
143
153
 
144
154
  ---
145
155
 
@@ -155,7 +165,7 @@ Message displayed when the user's device or browser is not supported.
155
165
  **Default:** `false`
156
166
 
157
167
  Whether a toggle button is displayed to allow the map to enter fullscreen mode.
158
- The button is only displayed when the map is `inline`.
168
+ The button is only displayed when the map is rendered inline.
159
169
 
160
170
  ---
161
171
 
@@ -164,7 +174,7 @@ The button is only displayed when the map is `inline`.
164
174
  **Default:** `true`
165
175
 
166
176
  Whether zoom control buttons are displayed.
167
- Zoom controls are not diplayed when the interface type is `touch`.
177
+ Zoom controls are not displayed when the interface type is 'touch'.
168
178
 
169
179
  ---
170
180
 
@@ -189,7 +199,7 @@ Fallback error message shown when the map fails to load.
189
199
  **Default:** `false`
190
200
 
191
201
  Whether an exit button is displayed.
192
- The exit button is only displayed when the behavour is `buttonFirst` or `hybrid` and the map is `fullscreen`.
202
+ The exit button is only displayed when the behaviour is `buttonFirst` or `hybrid` and the map is displayed fullscreen.
193
203
 
194
204
  ---
195
205
 
@@ -197,7 +207,7 @@ The exit button is only displayed when the behavour is `buttonFirst` or `hybrid`
197
207
  **Type:** `number | null`
198
208
  **Default:** `null`
199
209
 
200
- Optional viewport width breakpoint (in pixels) used by the `'hybrid'` behaviour.
210
+ Optional viewport width breakpoint (in pixels) used by the `hybrid` behaviour.
201
211
  When not set, defaults to `maxMobileWidth`.
202
212
 
203
213
  ---
@@ -205,8 +215,10 @@ When not set, defaults to `maxMobileWidth`.
205
215
  ### `keyboardHintText`
206
216
  **Type:** `string`
207
217
 
208
- HTML string providing keyboard shortcut instructions for assistive technology users.
209
- The hint text is displayed as a popup label when the `viewport` has focus.
218
+ HTML string shown as a tooltip on the viewport when it receives keyboard focus, prompting the user to open the keyboard shortcuts modal.
219
+
220
+ > [!NOTE]
221
+ > It is unlikely you will need to override this. If you do, keep the text short to avoid breaking the layout of the tooltip.
210
222
 
211
223
  ---
212
224
 
@@ -214,8 +226,13 @@ The hint text is displayed as a popup label when the `viewport` has focus.
214
226
  **Type:** `string`
215
227
  **Required**
216
228
 
217
- Accessible label describing the purpose of the map.
218
- This value is announced to screen readers.
229
+ Accessible name for the map viewport, which has a role of `application`. This label is announced by screen readers when the viewport receives focus and should describe the purpose of the map.
230
+
231
+ ```js
232
+ new InteractiveMap('map', {
233
+ mapLabel: 'Flood risk areas in England'
234
+ })
235
+ ```
219
236
 
220
237
  ---
221
238
 
@@ -223,7 +240,13 @@ This value is announced to screen readers.
223
240
  **Type:** `function`
224
241
  **Required**
225
242
 
226
- A factory function that returns a map provider instance, e.g., `maplibreProvider()`.
243
+ A function that returns a map provider the abstraction layer that interfaces with the underlying map engine. It is called only when the map is opened so the provider code is not sent to the user unless needed.
244
+
245
+ ```js
246
+ new InteractiveMap('map', {
247
+ mapProvider: maplibreProvider()
248
+ })
249
+ ```
227
250
 
228
251
  ---
229
252
 
@@ -233,8 +256,6 @@ A factory function that returns a map provider instance, e.g., `maplibreProvider
233
256
 
234
257
  Visual size of text and features in the map itself.
235
258
 
236
- **Possible values**
237
-
238
259
  | Possible values |
239
260
  |:--|
240
261
  | **'small'** *(default)*
@@ -260,7 +281,7 @@ See [MapStyleConfig](./api/map-style-config.md) for full details.
260
281
  **Type:** `string`
261
282
  **Default:** `'mv'`
262
283
 
263
- URL query parameter key used to persist map visibility state.
284
+ URL query parameter key used to persist map visibility state. Override if the default value clashes with an existing parameter on your page.
264
285
 
265
286
  ---
266
287
 
@@ -276,9 +297,9 @@ See [MarkerConfig](./api/marker-config.md) for full details.
276
297
  ### `symbolDefaults`
277
298
  **Type:** `Partial<SymbolDefaults>`
278
299
 
279
- App-wide defaults for symbol and marker appearance. These values apply across all markers and datasets unless a more specific value is set at the symbol or per-marker level. Any property omitted here falls back to the built-in default:
300
+ App-wide defaults for symbol and marker appearance.
280
301
 
281
- | Property | Built-in default |
302
+ | Property | Default |
282
303
  |---|---|
283
304
  | `symbol` | `'pin'` |
284
305
  | `backgroundColor` | `'#ca3535'` |
@@ -302,7 +323,7 @@ See [Symbol Config](./api/symbol-config.md) for the full property list.
302
323
  ### `maxExtent`
303
324
  **Type:** `[number, number, number, number]`
304
325
 
305
- Maximum viewable extent [west, south, east, north]. Passed directly to the map engine; implementation varies.
326
+ Maximum viewable extent [west, south, east, north]. Passed directly to the underlying map engine; how it is enforced depends on the provider.
306
327
 
307
328
  ---
308
329
 
@@ -370,7 +391,7 @@ Smaller zoom increment used for fine-grained zoom adjustments.
370
391
  **Type:** `string`
371
392
 
372
393
  Supplementary text appended to the existing page title.
373
- Only used when the beahviour is `buttonFirst` or `hybrid` and the map is displayed in `fullscreen` mode.
394
+ Only used when the behaviour is `buttonFirst` or `hybrid` and the map is displayed fullscreen.
374
395
 
375
396
  ---
376
397
 
@@ -385,7 +406,7 @@ Distance (in pixels) the map pans during standard pan interactions.
385
406
  ### `plugins`
386
407
  **Type:** `PluginDescriptor[]`
387
408
 
388
- Plugins to load.
409
+ Optional extensions that add features such as datasets, search, or custom panels to the map.
389
410
 
390
411
  See [PluginDescriptor](./plugins/plugin-descriptor.md) for full details.
391
412
 
@@ -395,7 +416,7 @@ See [PluginDescriptor](./plugins/plugin-descriptor.md) for full details.
395
416
  **Type:** `boolean`
396
417
  **Default:** `false`
397
418
 
398
- Controls whether closing the map (via the browser back button or the exit map button when `hasExitButton` is `true` and the map is fullscreen) destroys the map instance or hides it while preserving its current state. Set to `true` to keep the map state intact, which is useful for implementations like a toggle map view list view pattern.
419
+ Controls whether closing the map destroys the map instance or hides it while preserving its current state. When `true`, state is retained between open and close for example in a map/list toggle, a user can interact with the map, switch to the list view, then reopen the map and pick up exactly where they left off.
399
420
 
400
421
  ---
401
422
 
@@ -405,22 +426,28 @@ Controls whether closing the map (via the browser back button or the exit map bu
405
426
 
406
427
  Whether map text labels can be selected and read aloud by assistive technologies.
407
428
 
408
- > [!WARNING]
409
- > **Experimental:** This is a development flag. It currently only works with MapLibre and specific styles. Do **not** enable in production unless fully tested.
429
+ > [!CAUTION]
430
+ > This is experimental. It currently only works with MapLibre and specific styles. Do **not** enable in production unless fully tested.
410
431
 
411
432
  ---
412
433
 
413
434
  ### `reverseGeocodeProvider`
414
435
  **Type:** `function | null`
415
436
 
416
- A factory function that returns a reverse geocode provider instance, e.g., `openNamesProvider()`.
437
+ A function that returns a reverse geocode provider used to convert map coordinates to a place name, for example when announcing the current map position to screen reader users. Like the map provider, it is only called when the map is opened so the provider code is not sent to the user unless needed.
438
+
439
+ ```js
440
+ new InteractiveMap('map', {
441
+ reverseGeocodeProvider: openNamesProvider()
442
+ })
443
+ ```
417
444
 
418
445
  ---
419
446
 
420
447
  ### `transformRequest`
421
448
  **Type:** `function`
422
449
 
423
- Function to transform outgoing requests (e.g., to add authentication headers). Passed directly to MapLibre; other map engines may have their own equivalent. For ESRI SDK, this is handled in the EsriMapProvider configuration.
450
+ Function to transform outgoing requests, for example to add authentication headers. This option is specific to MapLibre and is passed directly to the underlying MapLibre instance.
424
451
 
425
452
  ```js
426
453
  (url, resourceType) => { url, headers, credentials }
@@ -429,7 +456,7 @@ Function to transform outgoing requests (e.g., to add authentication headers). P
429
456
  See the [MapLibre documentation](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/RequestParameters/) for full details.
430
457
 
431
458
  > [!NOTE]
432
- > This function is synchronous. For asynchronous authentication flows such as OAuth, consider alternative approaches like overriding the fetch prototype. Further guidance to follow.
459
+ > For ESRI SDK, request transformation is handled in the EsriMapProvider configuration rather than through this option.
433
460
 
434
461
  ---
435
462
 
@@ -488,7 +515,9 @@ Add a marker to the map.
488
515
  |-----------|------|-------------|
489
516
  | `id` | `string` | Unique marker identifier |
490
517
  | `coords` | `[number, number]` | Coordinates [lng, lat] or [easting, northing] depending on CRS |
491
- | `options` | [`MarkerOptions`](./api/marker-config.md#markeroptions) | Optional marker appearance options |
518
+ | `options` | `MarkerOptions` | Optional marker appearance options |
519
+
520
+ See [MarkerOptions](./api/marker-config.md#markeroptions) for configuration options.
492
521
 
493
522
  ```js
494
523
  interactiveMap.addMarker('home', [-0.1276, 51.5074], { backgroundColor: '#1d70b8' })
@@ -550,14 +579,14 @@ interactiveMap.addButton('my-menu', {
550
579
 
551
580
  ### `addPanel(id, config)`
552
581
 
553
- Add a panel to the UI at runtime. Focus is moved to the panel by default — set `focus: false` in the config to suppress this when adding panels on page load.
582
+ Adds a new panel with content to the UI at runtime. Focus is moved to the panel by default — set `focus: false` in the config to suppress this when adding panels on page load.
554
583
 
555
584
  | Parameter | Type | Description |
556
585
  |-----------|------|-------------|
557
586
  | `id` | `string` | Unique panel identifier |
558
587
  | `config` | `PanelDefinition` | Panel configuration |
559
588
 
560
- See [PanelDefinition](./api/panel-definition.md) for configuration options. When using this method, provide content via the `html` property.
589
+ See [PanelDefinition](./api/panel-definition.md) for all configuration options.
561
590
 
562
591
  ```js
563
592
  interactiveMap.addPanel('info-panel', {
@@ -573,7 +602,7 @@ interactiveMap.addPanel('info-panel', {
573
602
 
574
603
  ### `removePanel(id)`
575
604
 
576
- Remove a panel from the UI.
605
+ Removes a panel from the UI entirely. Use `hidePanel` instead if you want to show it again later.
577
606
 
578
607
  | Parameter | Type | Description |
579
608
  |-----------|------|-------------|
@@ -587,7 +616,7 @@ interactiveMap.removePanel('info-panel')
587
616
 
588
617
  ### `showPanel(id, options?)`
589
618
 
590
- Show a panel. Focus is moved to the panel by default — set `focus: false` to suppress this, useful when showing a panel and you want focus to remain on the button.
619
+ Shows a panel that already exists but is hidden. Focus is moved to the panel by default — set `focus: false` to suppress this, useful when you want focus to remain on the triggering button.
591
620
 
592
621
  | Parameter | Type | Description |
593
622
  |-----------|------|-------------|
@@ -605,7 +634,7 @@ interactiveMap.showPanel('info-panel', { focus: false })
605
634
 
606
635
  ### `hidePanel(id)`
607
636
 
608
- Hide a panel.
637
+ Hides a panel without removing it, preserving its content for when it is shown again.
609
638
 
610
639
  | Parameter | Type | Description |
611
640
  |-----------|------|-------------|
@@ -632,7 +661,7 @@ See [ControlDefinition](./api/control-definition.md) for configuration options.
632
661
 
633
662
  ### `setMode(mode)`
634
663
 
635
- Set the application mode.
664
+ Programmatically set the application mode. See the [`mode`](#mode) option for more detail.
636
665
 
637
666
  | Parameter | Type | Description |
638
667
  |-----------|------|-------------|
@@ -646,7 +675,7 @@ interactiveMap.setMode('fullscreen')
646
675
 
647
676
  ### `toggleButtonState(id, prop, value)`
648
677
 
649
- Set or toggle a button state.
678
+ Set or toggle a button state. Where applicable the corresponding ARIA attribute is updated — `aria-pressed`, `aria-disabled`, or `aria-expanded`.
650
679
 
651
680
  | Parameter | Type | Description |
652
681
  |-----------|------|-------------|
@@ -702,15 +731,15 @@ interactiveMap.fitToBounds({
702
731
 
703
732
  ---
704
733
 
705
- ### `setView(opts)`
734
+ ### `setView(options)`
706
735
 
707
736
  Set the map center and zoom. Safe zone padding is automatically applied.
708
737
 
709
738
  | Parameter | Type | Description |
710
739
  |-----------|------|-------------|
711
- | `opts` | `Object` | View options |
712
- | `opts.center` | `[number, number]` | Optional center [lng, lat] or [easting, northing] depending on CRS |
713
- | `opts.zoom` | `number` | Optional zoom level |
740
+ | `options` | `Object` | View options |
741
+ | `options.center` | `[number, number]` | Optional center [lng, lat] or [easting, northing] depending on CRS |
742
+ | `options.zoom` | `number` | Optional zoom level |
714
743
 
715
744
  ```js
716
745
  interactiveMap.setView({ center: [-0.1276, 51.5074], zoom: 12 })
@@ -32,8 +32,6 @@ This wrapper:
32
32
  * **Passes** configuration, plugins, and providers
33
33
  * **Exposes** events and methods to the host application
34
34
 
35
- > **Note:** Internally, the UI is implemented in React, but this is an implementation detail and not required knowledge for consumers.
36
-
37
35
  ---
38
36
 
39
37
  ## 2. Core Component
@@ -38,7 +38,7 @@
38
38
  background-image: url('/images/hero.png');
39
39
  background-repeat: no-repeat;
40
40
  background-position: center bottom;
41
- background-size: 200px;
41
+ background-size: 220px;
42
42
  }
43
43
  }
44
44
 
@@ -115,6 +115,83 @@
115
115
  flex: 1 0 auto;
116
116
  }
117
117
 
118
+ /* GOV.UK tabs — enhanced styles for all devices; React manages active state.
119
+ Extra specificity via .app-prose-scope required to override the theme. */
120
+ .govuk-tabs {
121
+ margin-top: 5px;
122
+ margin-bottom: 40px;
123
+ font-size: 1.1875rem;
124
+ line-height: 1.3157894737;
125
+ }
126
+
127
+ .app-prose-scope .govuk-tabs .govuk-tabs__list {
128
+ overflow: hidden;
129
+ margin: 0;
130
+ padding: 5px 0 0;
131
+ list-style: none;
132
+ border-bottom: 1px solid #b1b4b6;
133
+ }
134
+
135
+ .app-prose-scope .govuk-tabs .govuk-tabs__list-item {
136
+ position: relative;
137
+ float: left;
138
+ margin: 0 5px 0 0;
139
+ padding: 10px 20px;
140
+ background-color: #f3f2f1;
141
+ text-align: center;
142
+ }
143
+
144
+ .app-prose-scope .govuk-tabs__list-item::before {
145
+ content: none;
146
+ }
147
+
148
+ .app-prose-scope .govuk-tabs .govuk-tabs__list-item--selected {
149
+ margin-top: -5px;
150
+ padding: 14px 19px 15px;
151
+ border: 1px solid #b1b4b6;
152
+ border-bottom: 0;
153
+ background-color: #ffffff;
154
+ }
155
+
156
+ .app-prose-scope .govuk-tabs .govuk-tabs__tab {
157
+ display: inline-block;
158
+ margin-bottom: 0;
159
+ text-decoration: underline;
160
+ }
161
+
162
+ .app-prose-scope .govuk-tabs .govuk-tabs__tab:is(:link, :visited, :hover, :active) {
163
+ color: #0b0c0c;
164
+ }
165
+
166
+ .app-prose-scope .govuk-tabs .govuk-tabs__list-item--selected .govuk-tabs__tab {
167
+ text-decoration: none;
168
+ }
169
+
170
+ .app-prose-scope .govuk-tabs .govuk-tabs__tab::after {
171
+ content: "";
172
+ position: absolute;
173
+ inset: 0;
174
+ }
175
+
176
+ .app-prose-scope .govuk-tabs .govuk-tabs__panel {
177
+ padding: 0;
178
+ border: 1px solid #b1b4b6;
179
+ border-top: 0;
180
+ margin-bottom: 0;
181
+ }
182
+
183
+ .app-prose-scope .govuk-tabs .govuk-tabs__panel > :last-child {
184
+ margin-bottom: 0;
185
+ }
186
+
187
+ .app-prose-scope .govuk-tabs__panel--hidden {
188
+ display: none;
189
+ }
190
+
191
+ .app-prose-scope .govuk-tabs .app-code-block__pre {
192
+ margin: 0;
193
+ }
194
+
118
195
  /* Heading overides */
119
196
  .app-prose-scope *:not(.app-no-prose *) .govuk-heading-l {
120
197
  font-size: 2.25rem;
Binary file
@@ -1,4 +1,5 @@
1
1
  import DemoMapMarkerPanel from '../../demo/DemoMapMarkerPanel.js'
2
+ import CodeTabs from '../../demo/js/codeTabs.js'
2
3
 
3
4
  # Add a marker with a panel
4
5
 
@@ -6,54 +7,117 @@ Add markers to the map and allow users to select them. Selecting a marker fires
6
7
 
7
8
  <DemoMapMarkerPanel />
8
9
 
9
- ```js
10
- import InteractiveMap from '@defra/interactive-map'
11
- import maplibreProvider from '@defra/interactive-map/providers/maplibre'
12
- import createInteractPlugin from '@defra/interactive-map/plugins/interact'
13
-
14
- const interactPlugin = createInteractPlugin({
15
- deselectOnClickOutside: true
16
- })
17
-
18
- const map = new InteractiveMap('my-map', {
19
- behaviour: 'inline',
20
- mapProvider: maplibreProvider(),
21
- mapStyle: {
22
- url: 'https://your-tile-url/style.json',
23
- attribution: 'Your tile attribution'
10
+ <CodeTabs tabs={[
11
+ {
12
+ label: 'ESM',
13
+ language: 'js',
14
+ code: `
15
+ import InteractiveMap from '@defra/interactive-map'
16
+ import maplibreProvider from '@defra/interactive-map/providers/maplibre'
17
+ import createInteractPlugin from '@defra/interactive-map/plugins/interact'
18
+
19
+ const interactPlugin = createInteractPlugin({
20
+ deselectOnClickOutside: true
21
+ })
22
+
23
+ const map = new InteractiveMap('my-map', {
24
+ behaviour: 'inline',
25
+ mapProvider: maplibreProvider(),
26
+ mapStyle: {
27
+ url: 'https://your-tile-url/style.json',
28
+ attribution: 'Your tile attribution'
29
+ },
30
+ center: [-2.96, 54.43],
31
+ zoom: 15,
32
+ containerHeight: '500px',
33
+ plugins: [interactPlugin]
34
+ })
35
+
36
+ map.on('map:ready', () => {
37
+ map.addMarker('my-marker', [-2.96, 54.43])
38
+ interactPlugin.enable()
39
+ interactPlugin.selectMarker('my-marker')
40
+
41
+ map.addPanel('marker-info', {
42
+ focus: false,
43
+ label: 'Marker',
44
+ html: '<p class="govuk-body">Information about the selected marker</p>',
45
+ mobile: { slot: 'drawer', dismissible: true },
46
+ tablet: { slot: 'left-top', dismissible: true, width: '280px' },
47
+ desktop: { slot: 'left-top', dismissible: true, width: '280px' }
48
+ })
49
+ })
50
+
51
+ map.on('interact:selectionchange', ({ selectedMarkers }) => {
52
+ if (selectedMarkers.length > 0) {
53
+ map.showPanel('marker-info')
54
+ } else {
55
+ map.hidePanel('marker-info')
56
+ }
57
+ })
58
+
59
+ map.on('app:panelclosed', ({ panelId }) => {
60
+ if (panelId === 'marker-info') {
61
+ interactPlugin.unselectMarker('my-marker')
62
+ }
63
+ })
64
+ `
24
65
  },
25
- center: [-2.96, 54.43],
26
- zoom: 15,
27
- containerHeight: '500px',
28
- plugins: [interactPlugin]
29
- })
30
-
31
- map.on('map:ready', () => {
32
- map.addMarker('my-marker', [-2.96, 54.43])
33
- interactPlugin.enable()
34
- interactPlugin.selectMarker('my-marker')
35
-
36
- map.addPanel('marker-info', {
37
- focus: false,
38
- label: 'Marker',
39
- html: '<p class="govuk-body">Information about the selected marker</p>',
40
- mobile: { slot: 'drawer', dismissible: true },
41
- tablet: { slot: 'left-top', dismissible: true, width: '280px' },
42
- desktop: { slot: 'left-top', dismissible: true, width: '280px' }
43
- })
44
- })
45
-
46
- map.on('interact:selectionchange', ({ selectedMarkers }) => {
47
- if (selectedMarkers.length > 0) {
48
- map.showPanel('marker-info')
49
- } else {
50
- map.hidePanel('marker-info')
51
- }
52
- })
66
+ {
67
+ label: 'UMD',
68
+ language: 'html',
69
+ code: `
70
+ <script src="/your-assets-path/interactive-map/index.js"></script>
71
+ <script src="/your-assets-path/maplibre-provider/index.js"></script>
72
+ <script src="/your-assets-path/interact-plugin/index.js"></script>
73
+
74
+ <script>
75
+ const interactPlugin = defra.interactPlugin({
76
+ deselectOnClickOutside: true
77
+ })
78
+
79
+ const map = new defra.InteractiveMap('my-map', {
80
+ behaviour: 'inline',
81
+ mapProvider: defra.maplibreProvider(),
82
+ mapStyle: {
83
+ url: 'https://your-tile-url/style.json',
84
+ attribution: 'Your tile attribution'
85
+ },
86
+ center: [-2.96, 54.43],
87
+ zoom: 15,
88
+ containerHeight: '500px',
89
+ plugins: [interactPlugin]
90
+ })
91
+
92
+ map.on('map:ready', () => {
93
+ map.addMarker('my-marker', [-2.96, 54.43])
94
+ interactPlugin.enable()
95
+ interactPlugin.selectMarker('my-marker')
96
+
97
+ map.addPanel('marker-info', {
98
+ focus: false,
99
+ label: 'Marker',
100
+ html: '<p class="govuk-body">Information about the selected marker</p>',
101
+ mobile: { slot: 'drawer', dismissible: true },
102
+ tablet: { slot: 'left-top', dismissible: true, width: '280px' },
103
+ desktop: { slot: 'left-top', dismissible: true, width: '280px' }
104
+ })
105
+ })
106
+
107
+ map.on('interact:selectionchange', ({ selectedMarkers }) => {
108
+ if (selectedMarkers.length > 0) {
109
+ map.showPanel('marker-info')
110
+ } else {
111
+ map.hidePanel('marker-info')
112
+ }
113
+ })
53
114
 
54
- map.on('app:panelclosed', ({ panelId }) => {
55
- if (panelId === 'marker-info') {
56
- interactPlugin.unselectMarker('my-marker')
115
+ map.on('app:panelclosed', ({ panelId }) => {
116
+ if (panelId === 'marker-info') {
117
+ interactPlugin.unselectMarker('my-marker')
118
+ }
119
+ })
120
+ </script>
121
+ `
57
122
  }
58
- })
59
- ```
123
+ ]} />