@defra/interactive-map 0.0.42-fmp-4 → 0.0.43-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 (138) hide show
  1. package/dist/css/index.css +1 -1
  2. package/dist/esm/im-core.js +1 -1
  3. package/dist/esm/im-shell.js +1 -1
  4. package/dist/umd/im-core.js +1 -1
  5. package/dist/umd/index.js +1 -1
  6. package/docs/api/keyboard-shortcut-definition.md +102 -0
  7. package/docs/api.md +2 -0
  8. package/docs/building-a-plugin.md +1 -0
  9. package/docs/plugins/draw.md +1 -1
  10. package/docs/plugins/plugin-manifest.md +9 -0
  11. package/package.json +1 -1
  12. package/plugins/beta/frame/dist/esm/im-frame-plugin.js +1 -1
  13. package/plugins/beta/frame/dist/umd/im-frame-plugin.js +1 -1
  14. package/plugins/beta/frame/src/Frame.jsx +28 -2
  15. package/plugins/beta/map-styles/dist/umd/im-map-styles-plugin.js +1 -1
  16. package/plugins/beta/map-styles/dist/umd/index.js +1 -1
  17. package/plugins/datasets/dist/esm/im-datasets-plugin.js +1 -1
  18. package/plugins/datasets/dist/umd/im-datasets-plugin.js +1 -1
  19. package/plugins/datasets/src/registry/dataset.js +8 -12
  20. package/plugins/datasets/src/registry/dataset.test.js +17 -0
  21. package/plugins/datasets/src/registry/datasetRegistry.js +4 -5
  22. package/plugins/draw/dist/esm/im-draw-ml-adapter.js +1 -1
  23. package/plugins/draw/dist/esm/im-draw-ol-adapter.js +1 -1
  24. package/plugins/draw/dist/esm/im-draw-plugin.js +1 -1
  25. package/plugins/draw/dist/umd/im-draw-ml-adapter.js +1 -1
  26. package/plugins/draw/dist/umd/im-draw-ol-adapter.js +1 -1
  27. package/plugins/draw/dist/umd/im-draw-plugin.js +1 -1
  28. package/plugins/draw/src/DrawInit.jsx +23 -13
  29. package/plugins/draw/src/adapters/maplibre/modes/drawMode/lifecycle.js +15 -0
  30. package/plugins/draw/src/adapters/maplibre/modes/drawMode/lifecycle.test.js +18 -0
  31. package/plugins/draw/src/adapters/openlayers/draw/drawInput.js +9 -0
  32. package/plugins/draw/src/adapters/openlayers/point/drawPointMode.js +12 -1
  33. package/plugins/draw/src/adapters/openlayers/point/drawPointMode.test.js +18 -0
  34. package/plugins/draw/src/manifest.js +4 -1
  35. package/plugins/draw/src/manifest.test.js +19 -7
  36. package/plugins/interact/dist/esm/im-interact-plugin.js +1 -1
  37. package/plugins/interact/dist/umd/im-interact-plugin.js +1 -1
  38. package/plugins/interact/dist/umd/index.js +1 -1
  39. package/plugins/interact/src/events.js +6 -2
  40. package/plugins/interact/src/events.test.js +32 -0
  41. package/plugins/interact/src/hooks/useCrossHairVisibility.js +8 -3
  42. package/plugins/interact/src/hooks/useMapItemList.js +41 -12
  43. package/plugins/interact/src/hooks/useMapItemList.test.js +68 -3
  44. package/plugins/interact/src/utils/spatial.js +24 -1
  45. package/plugins/interact/src/utils/spatial.test.js +26 -1
  46. package/plugins/map-key/dist/css/index.css +1 -1
  47. package/plugins/map-key/dist/esm/im-map-key-plugin.js +1 -1
  48. package/plugins/map-key/dist/umd/im-map-key-plugin.js +1 -1
  49. package/plugins/map-key/dist/umd/index.js +1 -1
  50. package/plugins/map-key/src/components/Key/Key.jsx +3 -4
  51. package/plugins/map-key/src/components/Key/Key.module.scss +10 -8
  52. package/plugins/map-key/src/components/Key/KeyGroupItem.test.jsx +2 -2
  53. package/plugins/map-key/src/components/Key/KeyItem.jsx +2 -2
  54. package/plugins/map-key/src/components/Key/KeySvg.jsx +9 -7
  55. package/plugins/map-key/src/components/Key/KeySvg.test.jsx +4 -4
  56. package/plugins/map-key/src/components/Key/MapKey.jsx +5 -3
  57. package/plugins/map-key/src/manifest.js +1 -1
  58. package/plugins/map-key/src/utils/groupStyles.js +7 -0
  59. package/plugins/map-key/src/utils/mergeKeyGroupItems.js +12 -0
  60. package/plugins/map-key/src/utils/mergeKeyGroupItems.test.js +53 -0
  61. package/plugins/menu/dist/esm/im-menu-plugin.js +1 -1
  62. package/plugins/menu/dist/umd/im-menu-plugin.js +1 -1
  63. package/plugins/menu/dist/umd/index.js +1 -1
  64. package/plugins/menu/src/initialise/MenuInit.jsx +15 -3
  65. package/plugins/menu/src/initialise/MenuInit.test.jsx +25 -0
  66. package/plugins/menu/src/initialise/createMenu.js +3 -1
  67. package/plugins/menu/src/initialise/createMenu.test.js +20 -5
  68. package/plugins/menu/src/initialise/updateUrl.js +44 -0
  69. package/plugins/menu/src/initialise/updateUrl.test.js +91 -0
  70. package/plugins/menu/src/reducers/menuStateReducer.js +19 -1
  71. package/plugins/menu/src/reducers/menuStateReducer.test.js +53 -20
  72. package/plugins/menu/src/reducers/pluginState.js +1 -6
  73. package/plugins/menu/src/reducers/pluginState.test.js +0 -25
  74. package/plugins/search/dist/esm/im-search-plugin.js +1 -1
  75. package/plugins/search/dist/umd/im-search-plugin.js +1 -1
  76. package/plugins/search/src/manifest.js +5 -9
  77. package/plugins/search/src/manifest.test.js +5 -0
  78. package/providers/beta/openlayers/dist/esm/im-openlayers-provider.js +1 -1
  79. package/providers/beta/openlayers/dist/umd/im-openlayers-provider.js +1 -1
  80. package/providers/beta/openlayers/src/openlayersProvider.js +3 -3
  81. package/providers/beta/openlayers/src/openlayersProvider.test.js +6 -3
  82. package/providers/beta/openlayers/src/utils/queryFeatures.js +72 -0
  83. package/providers/beta/openlayers/src/utils/queryFeatures.test.js +122 -1
  84. package/providers/maplibre/src/defaults.test.js +26 -0
  85. package/src/App/components/CrossHair/CrossHair.jsx +19 -11
  86. package/src/App/components/CrossHair/CrossHair.module.scss +33 -12
  87. package/src/App/components/CrossHair/CrossHair.test.jsx +35 -11
  88. package/src/App/components/KeyboardHelp/KeyboardHelp.jsx +4 -1
  89. package/src/App/components/KeyboardHelp/KeyboardHelp.test.jsx +17 -0
  90. package/src/App/components/MapButton/MapButton.jsx +19 -7
  91. package/src/App/components/MapButton/MapButton.test.jsx +42 -4
  92. package/src/App/components/Markers/SymbolMarker.jsx +2 -3
  93. package/src/App/components/Markers/SymbolMarker.test.jsx +8 -9
  94. package/src/App/components/Panel/Panel.jsx +19 -20
  95. package/src/App/components/Panel/Panel.module.scss +5 -0
  96. package/src/App/components/Panel/Panel.test.jsx +69 -4
  97. package/src/App/components/PopupMenu/PopupMenu.jsx +7 -3
  98. package/src/App/components/PopupMenu/PopupMenu.test.jsx +71 -0
  99. package/src/App/components/PopupMenu/usePopupMenu.js +10 -9
  100. package/src/App/components/Viewport/Features.jsx +18 -4
  101. package/src/App/components/Viewport/Features.module.scss +4 -4
  102. package/src/App/components/Viewport/Features.test.jsx +155 -11
  103. package/src/App/components/Viewport/Viewport.jsx +3 -3
  104. package/src/App/controls/keyboardMappings.js +7 -2
  105. package/src/App/controls/keyboardMappings.test.js +21 -0
  106. package/src/App/controls/keyboardShortcuts.js +16 -2
  107. package/src/App/controls/keyboardShortcuts.test.js +21 -0
  108. package/src/App/hooks/useCrossHairAPI.js +29 -1
  109. package/src/App/hooks/useCrossHairAPI.test.js +17 -1
  110. package/src/App/hooks/useFeatureFocus.js +86 -28
  111. package/src/App/hooks/useFeatureFocus.test.js +167 -0
  112. package/src/App/hooks/useFeatureItems.js +1 -1
  113. package/src/App/hooks/useInterfaceAPI.js +2 -1
  114. package/src/App/hooks/useInterfaceAPI.test.js +9 -0
  115. package/src/App/hooks/useKeyboardShortcuts.js +66 -35
  116. package/src/App/hooks/useKeyboardShortcuts.test.js +52 -0
  117. package/src/App/hooks/useModalPanelBehaviour.js +48 -34
  118. package/src/App/hooks/useModalPanelBehaviour.test.js +59 -0
  119. package/src/App/layout/Layout.jsx +4 -2
  120. package/src/App/layout/Layout.test.jsx +21 -0
  121. package/src/App/layout/layout.module.scss +7 -1
  122. package/src/App/registry/keyboardShortcutRegistry.js +2 -2
  123. package/src/App/registry/keyboardShortcutRegistry.test.js +16 -0
  124. package/src/App/renderer/HtmlElementHost.jsx +12 -32
  125. package/src/App/renderer/mapButtons.js +4 -0
  126. package/src/App/renderer/mapButtons.test.js +20 -0
  127. package/src/App/renderer/mapPanels.js +33 -53
  128. package/src/App/renderer/mapPanels.test.js +29 -4
  129. package/src/App/renderer/slotHelpers.js +33 -0
  130. package/src/App/renderer/slotHelpers.test.js +79 -2
  131. package/src/InteractiveMap/InteractiveMap.js +13 -2
  132. package/src/InteractiveMap/InteractiveMap.test.js +33 -0
  133. package/src/config/appConfig.js +2 -2
  134. package/src/types.js +40 -0
  135. package/src/utils/getPanelElementId.js +4 -0
  136. package/src/utils/getPanelElementId.test.js +11 -0
  137. package/src/utils/getPanelRole.js +22 -0
  138. package/src/utils/getPanelRole.test.js +56 -0
@@ -0,0 +1,7 @@
1
+ export const HORIZONTAL_RAMP = 'horizontal-ramp'
2
+
3
+ const groupStyles = {
4
+ HORIZONTAL_RAMP
5
+ }
6
+
7
+ export default groupStyles
@@ -0,0 +1,12 @@
1
+ export const mergeKeyGroupItems = (groups, items) => {
2
+ if (!groups) {
3
+ return items
4
+ }
5
+ return items.map((item) => {
6
+ const { id } = item
7
+ if (groups[id]) {
8
+ return { ...item, ...groups[id] }
9
+ }
10
+ return item
11
+ })
12
+ }
@@ -0,0 +1,53 @@
1
+ import { mergeKeyGroupItems } from './mergeKeyGroupItems'
2
+
3
+ describe('mergeKeyGroupItems', () => {
4
+ it('returns items unchanged when groups is not provided', () => {
5
+ const items = [{ id: 'a', label: 'A' }, { id: 'b', label: 'B' }]
6
+
7
+ expect(mergeKeyGroupItems(undefined, items)).toBe(items)
8
+ })
9
+
10
+ it('returns items unchanged when groups is null', () => {
11
+ const items = [{ id: 'a', label: 'A' }]
12
+
13
+ expect(mergeKeyGroupItems(null, items)).toBe(items)
14
+ })
15
+
16
+ it('merges matching group data into an item', () => {
17
+ const items = [{ id: 'a', label: 'A' }]
18
+ const groups = { a: { group: 'Group 1' } }
19
+
20
+ expect(mergeKeyGroupItems(groups, items)).toEqual([
21
+ { id: 'a', label: 'A', group: 'Group 1' }
22
+ ])
23
+ })
24
+
25
+ it('overrides item properties with matching group properties', () => {
26
+ const items = [{ id: 'a', label: 'A' }]
27
+ const groups = { a: { label: 'Overridden' } }
28
+
29
+ expect(mergeKeyGroupItems(groups, items)).toEqual([
30
+ { id: 'a', label: 'Overridden' }
31
+ ])
32
+ })
33
+
34
+ it('leaves items without a matching group unchanged', () => {
35
+ const items = [{ id: 'a', label: 'A' }, { id: 'b', label: 'B' }]
36
+ const groups = { a: { group: 'Group 1' } }
37
+
38
+ expect(mergeKeyGroupItems(groups, items)).toEqual([
39
+ { id: 'a', label: 'A', group: 'Group 1' },
40
+ { id: 'b', label: 'B' }
41
+ ])
42
+ })
43
+
44
+ it('returns an empty array when items is empty', () => {
45
+ expect(mergeKeyGroupItems({ a: { group: 'Group 1' } }, [])).toEqual([])
46
+ })
47
+
48
+ it('handles an empty groups object as no matches', () => {
49
+ const items = [{ id: 'a', label: 'A' }]
50
+
51
+ expect(mergeKeyGroupItems({}, items)).toEqual(items)
52
+ })
53
+ })
@@ -1 +1 @@
1
- import{createContext as e,useContext as t,useRef as a,useEffect as n}from"preact/compat";import{jsx as r,jsxs as i,Fragment as u}from"preact/jsx-runtime";import o from"@babel/runtime/helpers/defineProperty";var l={},c=e=>{var t,a=(null===(t=l)||void 0===t||null===(t=t.current)||void 0===t?void 0:t.menuState)||{};for(var[n,r]of Object.entries(e)){var i=a[n];if(!r.includes(i))return!1}return!0},m=e=>{if(null==e)return!0;if("boolean"==typeof e)return e;if("object"==typeof e){for(var[t,a]of Object.entries(e))if("menu"===t&&!c(a))return!1;return!0}return!0},s=e("map-menu"),d=e=>"".concat(t(s),"-").concat(e),p=e=>{var{menuGroupItem:t,name:a,checked:n,onChange:u}=e,o=d("radio-".concat(t.id)),{visibleWhen:l}=t;return!l||m(l)?r("div",{className:'im-c-menu__item govuk-radios govuk-radios--small"',"data-module":"govuk-radios",children:i("div",{className:"govuk-radios__item",children:[r("input",{id:o,className:"govuk-radios__input",type:"radio",name:a,value:t.id,checked:n,onChange:u}),r("label",{className:"im-c-menu__item-label govuk-label govuk-radios__label",htmlFor:o,children:t.label})]})}):null},h=e=>{var{menuGroup:t,children:a}=e,n=t.groupLabel||t.label;if(!n)return r(u,{children:a});return r("div",{className:"govuk-form-group im-c-menu-group",children:i("fieldset",{className:"im-c-menu-group__fieldset",children:[r("legend",{className:"im-c-menu-group__legend",children:i("h3",{children:[" ",n," "]})}),a]})},t.id)},v=e=>{var{menuState:t,dispatch:a,menuGroup:n}=e,{id:i,items:u,visibleWhen:o}=n;if(!(!o||m(o)))return null;var l=t[i],c=e=>{a({type:"UPDATE_MENU_STATE",payload:{[i]:e.target.value}})};return r(h,{menuGroup:n,children:r("div",{className:"govuk-radios govuk-radios--small","data-module":"govuk-radios",children:u.map(e=>r(p,{menuGroupItem:e,name:i,checked:e.id===l,onChange:c},e.id))})})},b=e=>{var{dispatch:t,menuGroupItem:a,onChange:n,checked:u}=e,o="im-c-menu__item govuk-checkboxes govuk-checkboxes--small".concat(u?"":" im-c-menu__item--checked"),l=d("checkbox-".concat(a.id));return r("div",{className:o,"data-module":"govuk-checkboxes",children:i("div",{className:"govuk-checkboxes__item",children:[r("input",{className:"govuk-checkboxes__input",id:l,name:l,type:"checkbox",checked:u,onChange:e=>{var r,i=Boolean(null===(r=e.target)||void 0===r?void 0:r.checked);n&&n(i),t({type:"UPDATE_MENU_STATE",payload:{[a.id]:i}})}}),r("label",{className:"im-c-menu__item-label govuk-label govuk-checkboxes__label",htmlFor:l,children:a.label})]})},l)},g=e=>{var{dispatch:t,menuGroup:a,menuState:n}=e;return i(h,{menuGroup:a,children:[" ",a.items.map(e=>r(b,{dispatch:t,menuGroupItem:e,checked:n[e.id],onChange:e.handleOnChange},e.id))]})},f=e=>{var{menuGroup:t,dispatch:a,menuState:n}=e;return"checkbox"===t.type?r(g,{menuGroup:t,dispatch:a,menuState:n}):r(v,{menuGroup:t,dispatch:a,menuState:n})},k=e=>{};function _(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),a.push.apply(a,n)}return a}function y(e){for(var t=1;t<arguments.length;t++){var a=null!=arguments[t]?arguments[t]:{};t%2?_(Object(a),!0).forEach(function(t){o(e,t,a[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(a)):_(Object(a)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(a,t))})}return e}var S={InitComponent:function(e){var{pluginConfig:t,pluginState:r,mapState:i,services:u}=e,{dispatch:o}=r,{eventBus:c}=u,m=a(r);m.current=r,n(()=>{if(!i.isMapReady)return()=>{};(e=>{l=e})(m);var{menu:e}=t;return(e=>{var{menu:t,eventBus:a,dispatch:n,pluginStateRef:r}=e;return n({type:"SET_MENU",payload:{menu:t}}),a.requestOnce("datasets:registry",k),a.emitWhenRequested("menu:state",r)})({menu:e,eventBus:c,dispatch:o,pluginStateRef:m})},[i.isMapReady]),n(()=>c.emit("menu:changed",r.menuState),[r.menuState])},reducer:{initialState:{actionsArray:[],menu:[],menuState:{}},actions:{SET_MENU:(e,t)=>{var{menu:a}=t,n=(e=>{var t={};return e.forEach(e=>{var a;"radio"===e.type&&(t[e.id]=e.value||(null===(a=e.items)||void 0===a?void 0:a[0].value))}),t})(a);return y(y({},e),{},{menu:a,menuState:n})},UPDATE_MENU_STATE:(e,t)=>y(y({},e),{},{menuState:y(y({},e.menuState),t)})}},panels:[{id:"menu",label:"Layers",mobile:{slot:"drawer",modal:!0,dismissible:!0},tablet:{slot:"left-top",dismissible:!0,exclusive:!0,width:"260px"},desktop:{slot:"left-top",modal:!1,dismissible:!0,exclusive:!0,width:"280px"},render:e=>{var{pluginState:t,appConfig:a}=e,{menu:n=[],dispatch:u,menuState:o}=t,l=(null==a?void 0:a.id)||"map",c=n.some(e=>e.groupLabel),m="im-c-menu".concat(c?" im-c-menu--has-groups":"");return r(s,{value:"".concat(l,"-menu"),children:i("div",{className:m,children:[" ",n.map(e=>r(f,{menuGroup:e,dispatch:u,menuState:o},e.id))]})})}}],buttons:[{id:"menuButton",label:"Layers",panelId:"menu",iconId:"layersMenu",mobile:{slot:"top-left",showLabel:!0},tablet:{slot:"top-left",showLabel:!0},desktop:{slot:"top-left",showLabel:!0}}],icons:[{id:"layersMenu",svgContent:'<path d="M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z"></path><path d="M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12"></path><path d="M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17"></path>'}]};export{S as manifest};
1
+ import{createContext as e,useContext as t,useState as a,useRef as r,useEffect as n}from"preact/compat";import{jsx as i,jsxs as o,Fragment as u}from"preact/jsx-runtime";import l from"@babel/runtime/helpers/defineProperty";var c={},m=e=>{var t,a=(null===(t=c)||void 0===t||null===(t=t.current)||void 0===t?void 0:t.menuState)||{};for(var[r,n]of Object.entries(e)){var i=a[r];if(!n.includes(i))return!1}return!0},s=e=>{if(null==e)return!0;if("boolean"==typeof e)return e;if("object"==typeof e){for(var[t,a]of Object.entries(e))if("menu"===t&&!m(a))return!1;return!0}return!0},d=e("map-menu"),p=e=>"".concat(t(d),"-").concat(e),h=e=>{var{menuGroupItem:t,name:a,checked:r,onChange:n}=e,u=p("radio-".concat(t.id)),{visibleWhen:l}=t;return!l||s(l)?i("div",{className:'im-c-menu__item govuk-radios govuk-radios--small"',"data-module":"govuk-radios",children:o("div",{className:"govuk-radios__item",children:[i("input",{id:u,className:"govuk-radios__input",type:"radio",name:a,value:t.id,checked:r,onChange:n}),i("label",{className:"im-c-menu__item-label govuk-label govuk-radios__label",htmlFor:u,children:t.label})]})}):null},v=e=>{var{menuGroup:t,children:a}=e,r=t.groupLabel||t.label;if(!r)return i(u,{children:a});return i("div",{className:"govuk-form-group im-c-menu-group",children:o("fieldset",{className:"im-c-menu-group__fieldset",children:[i("legend",{className:"im-c-menu-group__legend",children:o("h3",{children:[" ",r," "]})}),a]})},t.id)},b=e=>{var{menuState:t,dispatch:a,menuGroup:r}=e,{id:n,items:o,visibleWhen:u}=r;if(!(!u||s(u)))return null;var l=t[n],c=e=>{a({type:"UPDATE_MENU_STATE",payload:{[n]:e.target.value}})};return i(v,{menuGroup:r,children:i("div",{className:"govuk-radios govuk-radios--small","data-module":"govuk-radios",children:o.map(e=>i(h,{menuGroupItem:e,name:n,checked:e.id===l,onChange:c},e.id))})})},g=e=>{var{dispatch:t,menuGroupItem:a,onChange:r,checked:n}=e,u="im-c-menu__item govuk-checkboxes govuk-checkboxes--small".concat(n?"":" im-c-menu__item--checked"),l=p("checkbox-".concat(a.id));return i("div",{className:u,"data-module":"govuk-checkboxes",children:o("div",{className:"govuk-checkboxes__item",children:[i("input",{className:"govuk-checkboxes__input",id:l,name:l,type:"checkbox",checked:n,onChange:e=>{var n,i=Boolean(null===(n=e.target)||void 0===n?void 0:n.checked);r&&r(i),t({type:"UPDATE_MENU_STATE",payload:{[a.id]:i}})}}),i("label",{className:"im-c-menu__item-label govuk-label govuk-checkboxes__label",htmlFor:l,children:a.label})]})},l)},f=e=>{var{dispatch:t,menuGroup:a,menuState:r}=e;return o(v,{menuGroup:a,children:[" ",a.items.map(e=>i(g,{dispatch:t,menuGroupItem:e,checked:r[e.id],onChange:e.handleOnChange},e.id))]})},k=e=>{var{menuGroup:t,dispatch:a,menuState:r}=e;return"checkbox"===t.type?i(f,{menuGroup:t,dispatch:a,menuState:r}):i(b,{menuGroup:t,dispatch:a,menuState:r})},_=e=>{},y=e=>{var{menu:t,eventBus:a,dispatch:r,pluginStateRef:n}=e,i=(e=>{var t=new URL(window.location.href),{searchParams:a}=t,r={};return e.forEach(e=>{var t=a.get(e.id);if("radio"===e.type){var n;r[e.id]=t||e.value||(null===(n=e.items)||void 0===n?void 0:n[0].value)}else{var{items:i}=e;i.forEach(e=>{var{id:a,checked:n}=e,i=t?t.includes(a):n;r[a]=i})}}),r})(t);return r({type:"SET_MENU",payload:{menu:t,menuState:i}}),a.requestOnce("datasets:registry",_),a.emitWhenRequested("menu:state",n)};function S(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),a.push.apply(a,r)}return a}function O(e){for(var t=1;t<arguments.length;t++){var a=null!=arguments[t]?arguments[t]:{};t%2?S(Object(a),!0).forEach(function(t){l(e,t,a[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(a)):S(Object(a)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(a,t))})}return e}var w={InitComponent:function(e){var{pluginConfig:t,pluginState:i,mapState:o,services:u}=e,{dispatch:l}=i,{eventBus:m}=u,[d,p]=a(!1),h=r(i);h.current=i,n(()=>{if(!o.isMapReady)return()=>{};(e=>{c=e})(h);var{menu:e}=t,a=y({menu:e,eventBus:m,dispatch:l,pluginStateRef:h});return p(!0),a},[o.isMapReady]),n(()=>{m.emit("menu:changed",i.menuState),d&&(e=>{var t=new URL(window.location.href),{searchParams:a}=t,{menu:r,menuState:n}=e;r.forEach(e=>{var{id:t,visibleWhen:r,type:i}=e;s(r)?"radio"===i?((e,t,a)=>{var{id:r}=e,n=t[r];a.set(r,n)})(e,n,a):((e,t,a)=>{var{id:r,items:n}=e,i=[];n.forEach(e=>{var{id:a}=e;t[a]&&i.push(a)}),i.length?a.set(r,i):a.delete(r)})(e,n,a):a.delete(t)}),t.search=decodeURIComponent(t.search),window.history.replaceState({},"",t.toString())})(i)},[i.menuState])},reducer:{initialState:{menu:[],menuState:{}},actions:{SET_MENU:(e,t)=>{var{menu:a,menuState:r}=t;return O(O({},e),{},{menu:a,menuState:r})},UPDATE_MENU_STATE:(e,t)=>O(O({},e),{},{menuState:O(O({},e.menuState),t)})}},panels:[{id:"menu",label:"Layers",mobile:{slot:"drawer",modal:!0,dismissible:!0},tablet:{slot:"left-top",dismissible:!0,exclusive:!0,width:"260px"},desktop:{slot:"left-top",modal:!1,dismissible:!0,exclusive:!0,width:"280px"},render:e=>{var{pluginState:t,appConfig:a}=e,{menu:r=[],dispatch:n,menuState:u}=t,l=(null==a?void 0:a.id)||"map",c=r.some(e=>e.groupLabel),m="im-c-menu".concat(c?" im-c-menu--has-groups":"");return i(d,{value:"".concat(l,"-menu"),children:o("div",{className:m,children:[" ",r.map(e=>i(k,{menuGroup:e,dispatch:n,menuState:u},e.id))]})})}}],buttons:[{id:"menuButton",label:"Layers",panelId:"menu",iconId:"layersMenu",mobile:{slot:"top-left",showLabel:!0},tablet:{slot:"top-left",showLabel:!0},desktop:{slot:"top-left",showLabel:!0}}],icons:[{id:"layersMenu",svgContent:'<path d="M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z"></path><path d="M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12"></path><path d="M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17"></path>'}]};export{w as manifest};
@@ -1 +1 @@
1
- "use strict";(this.webpackChunkdefra_DefraMap=this.webpackChunkdefra_DefraMap||[]).push([[217],{77(e,t,n){n.r(t),n.d(t,{manifest:()=>w});var r=n(738);function o(e){return o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},o(e)}function i(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,o,i,u,a=[],c=!0,l=!1;try{if(i=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;c=!1}else for(;!(c=(r=i.call(n)).done)&&(a.push(r.value),a.length!==t);c=!0);}catch(e){l=!0,o=e}finally{try{if(!c&&null!=n.return&&(u=n.return(),Object(u)!==u))return}finally{if(l)throw o}}return a}}(e,t)||function(e,t){if(e){if("string"==typeof e)return u(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?u(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function u(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}var a={},c=function(e){for(var t,n=(null===(t=a)||void 0===t||null===(t=t.current)||void 0===t?void 0:t.menuState)||{},r=0,o=Object.entries(e);r<o.length;r++){var u=i(o[r],2),c=u[0],l=u[1],s=n[c];if(!l.includes(s))return!1}return!0},l=function(e){if(null==e)return!0;if("boolean"==typeof e)return e;if("object"===o(e)){for(var t=0,n=Object.entries(e);t<n.length;t++){var r=i(n[t],2),u=r[0],a=r[1];if("menu"===u&&!c(a))return!1}return!0}return!0},s=(0,r.createContext)("map-menu"),m=function(e){return"".concat((0,r.useContext)(s),"-").concat(e)},f=n(287),p=function(e){var t=e.menuGroupItem,n=e.name,r=e.checked,o=e.onChange,i=m("radio-".concat(t.id)),u=t.visibleWhen;return!u||l(u)?(0,f.jsx)("div",{className:'im-c-menu__item govuk-radios govuk-radios--small"',"data-module":"govuk-radios",children:(0,f.jsxs)("div",{className:"govuk-radios__item",children:[(0,f.jsx)("input",{id:i,className:"govuk-radios__input",type:"radio",name:n,value:t.id,checked:r,onChange:o}),(0,f.jsx)("label",{className:"im-c-menu__item-label govuk-label govuk-radios__label",htmlFor:i,children:t.label})]})}):null},d=function(e){var t=e.menuGroup,n=e.children,r=t.groupLabel||t.label;return r?(0,f.jsx)("div",{className:"govuk-form-group im-c-menu-group",children:(0,f.jsxs)("fieldset",{className:"im-c-menu-group__fieldset",children:[(0,f.jsx)("legend",{className:"im-c-menu-group__legend",children:(0,f.jsxs)("h3",{children:[" ",r," "]})}),n]})},t.id):(0,f.jsx)(f.Fragment,{children:n})};function b(e){return b="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},b(e)}var v=function(e){var t=e.menuState,n=e.dispatch,r=e.menuGroup,o=r.id,i=r.items,u=r.visibleWhen;if(u&&!l(u))return null;var a=t[o],c=function(e){var t,r,i;n({type:"UPDATE_MENU_STATE",payload:(t={},r=o,i=e.target.value,(r=function(e){var t=function(e){if("object"!=b(e)||!e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!=b(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"==b(t)?t:t+""}(r))in t?Object.defineProperty(t,r,{value:i,enumerable:!0,configurable:!0,writable:!0}):t[r]=i,t)})};return(0,f.jsx)(d,{menuGroup:r,children:(0,f.jsx)("div",{className:"govuk-radios govuk-radios--small","data-module":"govuk-radios",children:i.map(function(e){return(0,f.jsx)(p,{menuGroupItem:e,name:o,checked:e.id===a,onChange:c},e.id)})})})};function y(e){return y="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},y(e)}var h=function(e){var t=e.dispatch,n=e.menuGroupItem,r=e.onChange,o=e.checked,i="im-c-menu__item govuk-checkboxes govuk-checkboxes--small".concat(o?"":" im-c-menu__item--checked"),u=m("checkbox-".concat(n.id));return(0,f.jsx)("div",{className:i,"data-module":"govuk-checkboxes",children:(0,f.jsxs)("div",{className:"govuk-checkboxes__item",children:[(0,f.jsx)("input",{className:"govuk-checkboxes__input",id:u,name:u,type:"checkbox",checked:o,onChange:function(e){var o,i,u,a,c=Boolean(null===(o=e.target)||void 0===o?void 0:o.checked);r&&r(c),t({type:"UPDATE_MENU_STATE",payload:(i={},u=n.id,a=c,(u=function(e){var t=function(e){if("object"!=y(e)||!e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!=y(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"==y(t)?t:t+""}(u))in i?Object.defineProperty(i,u,{value:a,enumerable:!0,configurable:!0,writable:!0}):i[u]=a,i)})}}),(0,f.jsx)("label",{className:"im-c-menu__item-label govuk-label govuk-checkboxes__label",htmlFor:u,children:n.label})]})},u)},g=function(e){var t=e.dispatch,n=e.menuGroup,r=e.menuState;return(0,f.jsxs)(d,{menuGroup:n,children:[" ",n.items.map(function(e){return(0,f.jsx)(h,{dispatch:t,menuGroupItem:e,checked:r[e.id],onChange:e.handleOnChange},e.id)})]})},S=function(e){var t=e.menuGroup,n=e.dispatch,r=e.menuState;return"checkbox"===t.type?(0,f.jsx)(g,{menuGroup:t,dispatch:n,menuState:r}):(0,f.jsx)(v,{menuGroup:t,dispatch:n,menuState:r})},j=function(e){};function k(e){return k="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},k(e)}function x(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function _(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?x(Object(n),!0).forEach(function(t){O(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):x(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}function O(e,t,n){return(t=function(e){var t=function(e){if("object"!=k(e)||!e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!=k(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"==k(t)?t:t+""}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var w={InitComponent:function(e){var t=e.pluginConfig,n=e.pluginState,o=e.mapState,i=e.services,u=n.dispatch,c=i.eventBus,l=(0,r.useRef)(n);l.current=n,(0,r.useEffect)(function(){return o.isMapReady?(function(e){a=e}(l),function(e){var t=e.eventBus,n=e.pluginStateRef;return(0,e.dispatch)({type:"SET_MENU",payload:{menu:e.menu}}),t.requestOnce("datasets:registry",j),t.emitWhenRequested("menu:state",n)}({menu:t.menu,eventBus:c,dispatch:u,pluginStateRef:l})):function(){}},[o.isMapReady]),(0,r.useEffect)(function(){return c.emit("menu:changed",n.menuState)},[n.menuState])},reducer:{initialState:{actionsArray:[],menu:[],menuState:{}},actions:{SET_MENU:function(e,t){var n=t.menu,r=function(e){var t={};return e.forEach(function(e){var n;"radio"===e.type&&(t[e.id]=e.value||(null===(n=e.items)||void 0===n?void 0:n[0].value))}),t}(n);return _(_({},e),{},{menu:n,menuState:r})},UPDATE_MENU_STATE:function(e,t){return _(_({},e),{},{menuState:_(_({},e.menuState),t)})}}},panels:[{id:"menu",label:"Layers",mobile:{slot:"drawer",modal:!0,dismissible:!0},tablet:{slot:"left-top",dismissible:!0,exclusive:!0,width:"260px"},desktop:{slot:"left-top",modal:!1,dismissible:!0,exclusive:!0,width:"280px"},render:function(e){var t=e.pluginState,n=e.appConfig,r=t.menu,o=void 0===r?[]:r,i=t.dispatch,u=t.menuState,a=(null==n?void 0:n.id)||"map",c=o.some(function(e){return e.groupLabel}),l="im-c-menu".concat(c?" im-c-menu--has-groups":"");return(0,f.jsx)(s,{value:"".concat(a,"-menu"),children:(0,f.jsxs)("div",{className:l,children:[" ",o.map(function(e){return(0,f.jsx)(S,{menuGroup:e,dispatch:i,menuState:u},e.id)})]})})}}],buttons:[{id:"menuButton",label:"Layers",panelId:"menu",iconId:"layersMenu",mobile:{slot:"top-left",showLabel:!0},tablet:{slot:"top-left",showLabel:!0},desktop:{slot:"top-left",showLabel:!0}}],icons:[{id:"layersMenu",svgContent:'<path d="M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z"></path><path d="M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12"></path><path d="M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17"></path>'}]}}}]);
1
+ "use strict";(this.webpackChunkdefra_DefraMap=this.webpackChunkdefra_DefraMap||[]).push([[217],{742(e,t,n){n.r(t),n.d(t,{manifest:()=>E});var r=n(738);function o(e){return o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},o(e)}function i(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,o,i,u,a=[],c=!0,l=!1;try{if(i=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;c=!1}else for(;!(c=(r=i.call(n)).done)&&(a.push(r.value),a.length!==t);c=!0);}catch(e){l=!0,o=e}finally{try{if(!c&&null!=n.return&&(u=n.return(),Object(u)!==u))return}finally{if(l)throw o}}return a}}(e,t)||function(e,t){if(e){if("string"==typeof e)return u(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?u(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function u(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}var a={},c=function(e){for(var t,n=(null===(t=a)||void 0===t||null===(t=t.current)||void 0===t?void 0:t.menuState)||{},r=0,o=Object.entries(e);r<o.length;r++){var u=i(o[r],2),c=u[0],l=u[1],s=n[c];if(!l.includes(s))return!1}return!0},l=function(e){if(null==e)return!0;if("boolean"==typeof e)return e;if("object"===o(e)){for(var t=0,n=Object.entries(e);t<n.length;t++){var r=i(n[t],2),u=r[0],a=r[1];if("menu"===u&&!c(a))return!1}return!0}return!0},s=(0,r.createContext)("map-menu"),m=function(e){return"".concat((0,r.useContext)(s),"-").concat(e)},f=n(287),d=function(e){var t=e.menuGroupItem,n=e.name,r=e.checked,o=e.onChange,i=m("radio-".concat(t.id)),u=t.visibleWhen;return!u||l(u)?(0,f.jsx)("div",{className:'im-c-menu__item govuk-radios govuk-radios--small"',"data-module":"govuk-radios",children:(0,f.jsxs)("div",{className:"govuk-radios__item",children:[(0,f.jsx)("input",{id:i,className:"govuk-radios__input",type:"radio",name:n,value:t.id,checked:r,onChange:o}),(0,f.jsx)("label",{className:"im-c-menu__item-label govuk-label govuk-radios__label",htmlFor:i,children:t.label})]})}):null},p=function(e){var t=e.menuGroup,n=e.children,r=t.groupLabel||t.label;return r?(0,f.jsx)("div",{className:"govuk-form-group im-c-menu-group",children:(0,f.jsxs)("fieldset",{className:"im-c-menu-group__fieldset",children:[(0,f.jsx)("legend",{className:"im-c-menu-group__legend",children:(0,f.jsxs)("h3",{children:[" ",r," "]})}),n]})},t.id):(0,f.jsx)(f.Fragment,{children:n})};function b(e){return b="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},b(e)}var v=function(e){var t=e.menuState,n=e.dispatch,r=e.menuGroup,o=r.id,i=r.items,u=r.visibleWhen;if(u&&!l(u))return null;var a=t[o],c=function(e){var t,r,i;n({type:"UPDATE_MENU_STATE",payload:(t={},r=o,i=e.target.value,(r=function(e){var t=function(e){if("object"!=b(e)||!e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!=b(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"==b(t)?t:t+""}(r))in t?Object.defineProperty(t,r,{value:i,enumerable:!0,configurable:!0,writable:!0}):t[r]=i,t)})};return(0,f.jsx)(p,{menuGroup:r,children:(0,f.jsx)("div",{className:"govuk-radios govuk-radios--small","data-module":"govuk-radios",children:i.map(function(e){return(0,f.jsx)(d,{menuGroupItem:e,name:o,checked:e.id===a,onChange:c},e.id)})})})};function y(e){return y="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},y(e)}var h=function(e){var t=e.dispatch,n=e.menuGroupItem,r=e.onChange,o=e.checked,i="im-c-menu__item govuk-checkboxes govuk-checkboxes--small".concat(o?"":" im-c-menu__item--checked"),u=m("checkbox-".concat(n.id));return(0,f.jsx)("div",{className:i,"data-module":"govuk-checkboxes",children:(0,f.jsxs)("div",{className:"govuk-checkboxes__item",children:[(0,f.jsx)("input",{className:"govuk-checkboxes__input",id:u,name:u,type:"checkbox",checked:o,onChange:function(e){var o,i,u,a,c=Boolean(null===(o=e.target)||void 0===o?void 0:o.checked);r&&r(c),t({type:"UPDATE_MENU_STATE",payload:(i={},u=n.id,a=c,(u=function(e){var t=function(e){if("object"!=y(e)||!e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!=y(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"==y(t)?t:t+""}(u))in i?Object.defineProperty(i,u,{value:a,enumerable:!0,configurable:!0,writable:!0}):i[u]=a,i)})}}),(0,f.jsx)("label",{className:"im-c-menu__item-label govuk-label govuk-checkboxes__label",htmlFor:u,children:n.label})]})},u)},g=function(e){var t=e.dispatch,n=e.menuGroup,r=e.menuState;return(0,f.jsxs)(p,{menuGroup:n,children:[" ",n.items.map(function(e){return(0,f.jsx)(h,{dispatch:t,menuGroupItem:e,checked:r[e.id],onChange:e.handleOnChange},e.id)})]})},S=function(e){var t=e.menuGroup,n=e.dispatch,r=e.menuState;return"checkbox"===t.type?(0,f.jsx)(g,{menuGroup:t,dispatch:n,menuState:r}):(0,f.jsx)(v,{menuGroup:t,dispatch:n,menuState:r})},j=function(e){};function k(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function x(e){return x="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},x(e)}function w(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function _(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?w(Object(n),!0).forEach(function(t){O(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):w(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}function O(e,t,n){return(t=function(e){var t=function(e){if("object"!=x(e)||!e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!=x(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"==x(t)?t:t+""}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var E={InitComponent:function(e){var t,n,o=e.pluginConfig,i=e.pluginState,u=e.mapState,c=e.services,s=i.dispatch,m=c.eventBus,f=(t=(0,r.useState)(!1),n=2,function(e){if(Array.isArray(e))return e}(t)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,o,i,u,a=[],c=!0,l=!1;try{if(i=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;c=!1}else for(;!(c=(r=i.call(n)).done)&&(a.push(r.value),a.length!==t);c=!0);}catch(e){l=!0,o=e}finally{try{if(!c&&null!=n.return&&(u=n.return(),Object(u)!==u))return}finally{if(l)throw o}}return a}}(t,n)||function(e,t){if(e){if("string"==typeof e)return k(e,t);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?k(e,t):void 0}}(t,n)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()),d=f[0],p=f[1],b=(0,r.useRef)(i);b.current=i,(0,r.useEffect)(function(){if(!u.isMapReady)return function(){};!function(e){a=e}(b);var e=function(e){var t=e.menu,n=e.eventBus,r=e.dispatch,o=e.pluginStateRef,i=function(e){var t=new URL(window.location.href).searchParams,n={};return e.forEach(function(e){var r,o=t.get(e.id);"radio"===e.type?n[e.id]=o||e.value||(null===(r=e.items)||void 0===r?void 0:r[0].value):e.items.forEach(function(e){var t=e.id,r=e.checked,i=o?o.includes(t):r;n[t]=i})}),n}(t);return r({type:"SET_MENU",payload:{menu:t,menuState:i}}),n.requestOnce("datasets:registry",j),n.emitWhenRequested("menu:state",o)}({menu:o.menu,eventBus:m,dispatch:s,pluginStateRef:b});return p(!0),e},[u.isMapReady]),(0,r.useEffect)(function(){m.emit("menu:changed",i.menuState),d&&function(e){var t=new URL(window.location.href),n=t.searchParams,r=e.menu,o=e.menuState;r.forEach(function(e){var t=e.id,r=e.visibleWhen,i=e.type;l(r)?"radio"===i?function(e,t,n){var r=e.id,o=t[r];n.set(r,o)}(e,o,n):function(e,t,n){var r=e.id,o=e.items,i=[];o.forEach(function(e){var n=e.id;t[n]&&i.push(n)}),i.length?n.set(r,i):n.delete(r)}(e,o,n):n.delete(t)}),t.search=decodeURIComponent(t.search),window.history.replaceState({},"",t.toString())}(i)},[i.menuState])},reducer:{initialState:{menu:[],menuState:{}},actions:{SET_MENU:function(e,t){var n=t.menu,r=t.menuState;return _(_({},e),{},{menu:n,menuState:r})},UPDATE_MENU_STATE:function(e,t){return _(_({},e),{},{menuState:_(_({},e.menuState),t)})}}},panels:[{id:"menu",label:"Layers",mobile:{slot:"drawer",modal:!0,dismissible:!0},tablet:{slot:"left-top",dismissible:!0,exclusive:!0,width:"260px"},desktop:{slot:"left-top",modal:!1,dismissible:!0,exclusive:!0,width:"280px"},render:function(e){var t=e.pluginState,n=e.appConfig,r=t.menu,o=void 0===r?[]:r,i=t.dispatch,u=t.menuState,a=(null==n?void 0:n.id)||"map",c=o.some(function(e){return e.groupLabel}),l="im-c-menu".concat(c?" im-c-menu--has-groups":"");return(0,f.jsx)(s,{value:"".concat(a,"-menu"),children:(0,f.jsxs)("div",{className:l,children:[" ",o.map(function(e){return(0,f.jsx)(S,{menuGroup:e,dispatch:i,menuState:u},e.id)})]})})}}],buttons:[{id:"menuButton",label:"Layers",panelId:"menu",iconId:"layersMenu",mobile:{slot:"top-left",showLabel:!0},tablet:{slot:"top-left",showLabel:!0},desktop:{slot:"top-left",showLabel:!0}}],icons:[{id:"layersMenu",svgContent:'<path d="M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z"></path><path d="M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12"></path><path d="M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17"></path>'}]}}}]);
@@ -1,2 +1,2 @@
1
1
  /*! For license information please see index.js.LICENSE.txt */
2
- !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("defra",[],t):"object"==typeof exports?exports.defra=t():(e.defra=e.defra||{},e.defra.menuPlugin=t())}(this,()=>(()=>{"use strict";var e,t,r={738(e){e.exports=preactCompat},287(e){e.exports=preactJsxRuntime}},n={};function o(e){var t=n[e];if(void 0!==t)return t.exports;var i=n[e]={exports:{}};return r[e](i,i.exports,o),i.exports}o.m=r,o.d=(e,t)=>{for(var r in t)o.o(t,r)&&!o.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},o.f={},o.e=e=>Promise.all(Object.keys(o.f).reduce((t,r)=>(o.f[r](e,t),t),[])),o.u=e=>"im-menu-plugin.js",o.miniCssF=e=>{},o.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),e={},t="defra.menuPlugin:",o.l=(r,n,i,a)=>{if(e[r])e[r].push(n);else{var u,c;if(void 0!==i)for(var f=document.getElementsByTagName("script"),p=0;p<f.length;p++){var l=f[p];if(l.getAttribute("src")==r||l.getAttribute("data-webpack")==t+i){u=l;break}}u||(c=!0,(u=document.createElement("script")).charset="utf-8",o.nc&&u.setAttribute("nonce",o.nc),u.setAttribute("data-webpack",t+i),u.src=r),e[r]=[n];var s=(t,n)=>{u.onerror=u.onload=null,clearTimeout(d);var o=e[r];if(delete e[r],u.parentNode&&u.parentNode.removeChild(u),o&&o.forEach(e=>e(n)),t)return t(n)},d=setTimeout(s.bind(null,void 0,{type:"timeout",target:u}),12e4);u.onerror=s.bind(null,u.onerror),u.onload=s.bind(null,u.onload),c&&document.head.appendChild(u)}},o.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{var e;o.g.importScripts&&(e=o.g.location+"");var t=o.g.document;if(!e&&t&&(t.currentScript&&"SCRIPT"===t.currentScript.tagName.toUpperCase()&&(e=t.currentScript.src),!e)){var r=t.getElementsByTagName("script");if(r.length)for(var n=r.length-1;n>-1&&(!e||!/^http(s?):/.test(e));)e=r[n--].src}if(!e)throw new Error("Automatic publicPath is not supported in this browser");e=e.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),o.p=e})(),(()=>{var e={57:0};o.f.j=(t,r)=>{var n=o.o(e,t)?e[t]:void 0;if(0!==n)if(n)r.push(n[2]);else{var i=new Promise((r,o)=>n=e[t]=[r,o]);r.push(n[2]=i);var a=o.p+o.u(t),u=new Error;o.l(a,r=>{if(o.o(e,t)&&(0!==(n=e[t])&&(e[t]=void 0),n)){var i=r&&("load"===r.type?"missing":r.type),a=r&&r.target&&r.target.src;u.message="Loading chunk "+t+" failed.\n("+i+": "+a+")",u.name="ChunkLoadError",u.type=i,u.request=a,n[1](u)}},"chunk-"+t,t)}};var t=(t,r)=>{var n,i,[a,u,c]=r,f=0;if(a.some(t=>0!==e[t])){for(n in u)o.o(u,n)&&(o.m[n]=u[n]);c&&c(o)}for(t&&t(r);f<a.length;f++)i=a[f],o.o(e,i)&&e[i]&&e[i][0](),e[i]=0},r=this.webpackChunkdefra_DefraMap=this.webpackChunkdefra_DefraMap||[];r.forEach(t.bind(null,0)),r.push=t.bind(null,r.push.bind(r))})();var i={};function a(e){return a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},a(e)}function u(){var e,t,r="function"==typeof Symbol?Symbol:{},n=r.iterator||"@@iterator",o=r.toStringTag||"@@toStringTag";function i(r,n,o,i){var u=n&&n.prototype instanceof f?n:f,p=Object.create(u.prototype);return c(p,"_invoke",function(r,n,o){var i,u,c,f=0,p=o||[],l=!1,s={p:0,n:0,v:e,a:d,f:d.bind(e,4),d:function(t,r){return i=t,u=0,c=e,s.n=r,a}};function d(r,n){for(u=r,c=n,t=0;!l&&f&&!o&&t<p.length;t++){var o,i=p[t],d=s.p,b=i[2];r>3?(o=b===n)&&(c=i[(u=i[4])?5:(u=3,3)],i[4]=i[5]=e):i[0]<=d&&((o=r<2&&d<i[1])?(u=0,s.v=n,s.n=i[1]):d<b&&(o=r<3||i[0]>n||n>b)&&(i[4]=r,i[5]=n,s.n=b,u=0))}if(o||r>1)return a;throw l=!0,n}return function(o,p,b){if(f>1)throw TypeError("Generator is already running");for(l&&1===p&&d(p,b),u=p,c=b;(t=u<2?e:c)||!l;){i||(u?u<3?(u>1&&(s.n=-1),d(u,c)):s.n=c:s.v=c);try{if(f=2,i){if(u||(o="next"),t=i[o]){if(!(t=t.call(i,c)))throw TypeError("iterator result is not an object");if(!t.done)return t;c=t.value,u<2&&(u=0)}else 1===u&&(t=i.return)&&t.call(i),u<2&&(c=TypeError("The iterator does not provide a '"+o+"' method"),u=1);i=e}else if((t=(l=s.n<0)?c:r.call(n,s))!==a)break}catch(t){i=e,u=1,c=t}finally{f=1}}return{value:t,done:l}}}(r,o,i),!0),p}var a={};function f(){}function p(){}function l(){}t=Object.getPrototypeOf;var s=[][n]?t(t([][n]())):(c(t={},n,function(){return this}),t),d=l.prototype=f.prototype=Object.create(s);function b(e){return Object.setPrototypeOf?Object.setPrototypeOf(e,l):(e.__proto__=l,c(e,o,"GeneratorFunction")),e.prototype=Object.create(d),e}return p.prototype=l,c(d,"constructor",l),c(l,"constructor",p),p.displayName="GeneratorFunction",c(l,o,"GeneratorFunction"),c(d),c(d,o,"Generator"),c(d,n,function(){return this}),c(d,"toString",function(){return"[object Generator]"}),(u=function(){return{w:i,m:b}})()}function c(e,t,r,n){var o=Object.defineProperty;try{o({},"",{})}catch(e){o=0}c=function(e,t,r,n){function i(t,r){c(e,t,function(e){return this._invoke(t,r,e)})}t?o?o(e,t,{value:r,enumerable:!n,configurable:!n,writable:!n}):e[t]=r:(i("next",0),i("throw",1),i("return",2))},c(e,t,r,n)}function f(e,t,r,n,o,i,a){try{var u=e[i](a),c=u.value}catch(e){return void r(e)}u.done?t(c):Promise.resolve(c).then(n,o)}function p(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),r.push.apply(r,n)}return r}function l(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?p(Object(r),!0).forEach(function(t){s(e,t,r[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):p(Object(r)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))})}return e}function s(e,t,r){return(t=function(e){var t=function(e){if("object"!=a(e)||!e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var r=t.call(e,"string");if("object"!=a(r))return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"==a(t)?t:t+""}(t))in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function d(){var e,t;return l(l({noKeyItemText:"No features displayed"},arguments.length>0&&void 0!==arguments[0]?arguments[0]:{}),{},{id:"menu",load:(e=u().m(function e(){var t;return u().w(function(e){for(;;)switch(e.n){case 0:return e.n=1,o.e(217).then(o.bind(o,77));case 1:return t=e.v.manifest,e.a(2,t)}},e)}),t=function(){var t=this,r=arguments;return new Promise(function(n,o){var i=e.apply(t,r);function a(e){f(i,n,o,a,u,"next",e)}function u(e){f(i,n,o,a,u,"throw",e)}a(void 0)})},function(){return t.apply(this,arguments)})})}return o.d(i,{default:()=>d}),i.default})());
2
+ !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("defra",[],t):"object"==typeof exports?exports.defra=t():(e.defra=e.defra||{},e.defra.menuPlugin=t())}(this,()=>(()=>{"use strict";var e,t,r={738(e){e.exports=preactCompat},287(e){e.exports=preactJsxRuntime}},n={};function o(e){var t=n[e];if(void 0!==t)return t.exports;var i=n[e]={exports:{}};return r[e](i,i.exports,o),i.exports}o.m=r,o.d=(e,t)=>{for(var r in t)o.o(t,r)&&!o.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},o.f={},o.e=e=>Promise.all(Object.keys(o.f).reduce((t,r)=>(o.f[r](e,t),t),[])),o.u=e=>"im-menu-plugin.js",o.miniCssF=e=>{},o.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),e={},t="defra.menuPlugin:",o.l=(r,n,i,a)=>{if(e[r])e[r].push(n);else{var u,c;if(void 0!==i)for(var f=document.getElementsByTagName("script"),p=0;p<f.length;p++){var l=f[p];if(l.getAttribute("src")==r||l.getAttribute("data-webpack")==t+i){u=l;break}}u||(c=!0,(u=document.createElement("script")).charset="utf-8",o.nc&&u.setAttribute("nonce",o.nc),u.setAttribute("data-webpack",t+i),u.src=r),e[r]=[n];var s=(t,n)=>{u.onerror=u.onload=null,clearTimeout(d);var o=e[r];if(delete e[r],u.parentNode&&u.parentNode.removeChild(u),o&&o.forEach(e=>e(n)),t)return t(n)},d=setTimeout(s.bind(null,void 0,{type:"timeout",target:u}),12e4);u.onerror=s.bind(null,u.onerror),u.onload=s.bind(null,u.onload),c&&document.head.appendChild(u)}},o.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{var e;o.g.importScripts&&(e=o.g.location+"");var t=o.g.document;if(!e&&t&&(t.currentScript&&"SCRIPT"===t.currentScript.tagName.toUpperCase()&&(e=t.currentScript.src),!e)){var r=t.getElementsByTagName("script");if(r.length)for(var n=r.length-1;n>-1&&(!e||!/^http(s?):/.test(e));)e=r[n--].src}if(!e)throw new Error("Automatic publicPath is not supported in this browser");e=e.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),o.p=e})(),(()=>{var e={57:0};o.f.j=(t,r)=>{var n=o.o(e,t)?e[t]:void 0;if(0!==n)if(n)r.push(n[2]);else{var i=new Promise((r,o)=>n=e[t]=[r,o]);r.push(n[2]=i);var a=o.p+o.u(t),u=new Error;o.l(a,r=>{if(o.o(e,t)&&(0!==(n=e[t])&&(e[t]=void 0),n)){var i=r&&("load"===r.type?"missing":r.type),a=r&&r.target&&r.target.src;u.message="Loading chunk "+t+" failed.\n("+i+": "+a+")",u.name="ChunkLoadError",u.type=i,u.request=a,n[1](u)}},"chunk-"+t,t)}};var t=(t,r)=>{var n,i,[a,u,c]=r,f=0;if(a.some(t=>0!==e[t])){for(n in u)o.o(u,n)&&(o.m[n]=u[n]);c&&c(o)}for(t&&t(r);f<a.length;f++)i=a[f],o.o(e,i)&&e[i]&&e[i][0](),e[i]=0},r=this.webpackChunkdefra_DefraMap=this.webpackChunkdefra_DefraMap||[];r.forEach(t.bind(null,0)),r.push=t.bind(null,r.push.bind(r))})();var i={};function a(e){return a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},a(e)}function u(){var e,t,r="function"==typeof Symbol?Symbol:{},n=r.iterator||"@@iterator",o=r.toStringTag||"@@toStringTag";function i(r,n,o,i){var u=n&&n.prototype instanceof f?n:f,p=Object.create(u.prototype);return c(p,"_invoke",function(r,n,o){var i,u,c,f=0,p=o||[],l=!1,s={p:0,n:0,v:e,a:d,f:d.bind(e,4),d:function(t,r){return i=t,u=0,c=e,s.n=r,a}};function d(r,n){for(u=r,c=n,t=0;!l&&f&&!o&&t<p.length;t++){var o,i=p[t],d=s.p,b=i[2];r>3?(o=b===n)&&(c=i[(u=i[4])?5:(u=3,3)],i[4]=i[5]=e):i[0]<=d&&((o=r<2&&d<i[1])?(u=0,s.v=n,s.n=i[1]):d<b&&(o=r<3||i[0]>n||n>b)&&(i[4]=r,i[5]=n,s.n=b,u=0))}if(o||r>1)return a;throw l=!0,n}return function(o,p,b){if(f>1)throw TypeError("Generator is already running");for(l&&1===p&&d(p,b),u=p,c=b;(t=u<2?e:c)||!l;){i||(u?u<3?(u>1&&(s.n=-1),d(u,c)):s.n=c:s.v=c);try{if(f=2,i){if(u||(o="next"),t=i[o]){if(!(t=t.call(i,c)))throw TypeError("iterator result is not an object");if(!t.done)return t;c=t.value,u<2&&(u=0)}else 1===u&&(t=i.return)&&t.call(i),u<2&&(c=TypeError("The iterator does not provide a '"+o+"' method"),u=1);i=e}else if((t=(l=s.n<0)?c:r.call(n,s))!==a)break}catch(t){i=e,u=1,c=t}finally{f=1}}return{value:t,done:l}}}(r,o,i),!0),p}var a={};function f(){}function p(){}function l(){}t=Object.getPrototypeOf;var s=[][n]?t(t([][n]())):(c(t={},n,function(){return this}),t),d=l.prototype=f.prototype=Object.create(s);function b(e){return Object.setPrototypeOf?Object.setPrototypeOf(e,l):(e.__proto__=l,c(e,o,"GeneratorFunction")),e.prototype=Object.create(d),e}return p.prototype=l,c(d,"constructor",l),c(l,"constructor",p),p.displayName="GeneratorFunction",c(l,o,"GeneratorFunction"),c(d),c(d,o,"Generator"),c(d,n,function(){return this}),c(d,"toString",function(){return"[object Generator]"}),(u=function(){return{w:i,m:b}})()}function c(e,t,r,n){var o=Object.defineProperty;try{o({},"",{})}catch(e){o=0}c=function(e,t,r,n){function i(t,r){c(e,t,function(e){return this._invoke(t,r,e)})}t?o?o(e,t,{value:r,enumerable:!n,configurable:!n,writable:!n}):e[t]=r:(i("next",0),i("throw",1),i("return",2))},c(e,t,r,n)}function f(e,t,r,n,o,i,a){try{var u=e[i](a),c=u.value}catch(e){return void r(e)}u.done?t(c):Promise.resolve(c).then(n,o)}function p(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),r.push.apply(r,n)}return r}function l(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?p(Object(r),!0).forEach(function(t){s(e,t,r[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):p(Object(r)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))})}return e}function s(e,t,r){return(t=function(e){var t=function(e){if("object"!=a(e)||!e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var r=t.call(e,"string");if("object"!=a(r))return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"==a(t)?t:t+""}(t))in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function d(){var e,t;return l(l({noKeyItemText:"No features displayed"},arguments.length>0&&void 0!==arguments[0]?arguments[0]:{}),{},{id:"menu",load:(e=u().m(function e(){var t;return u().w(function(e){for(;;)switch(e.n){case 0:return e.n=1,o.e(217).then(o.bind(o,742));case 1:return t=e.v.manifest,e.a(2,t)}},e)}),t=function(){var t=this,r=arguments;return new Promise(function(n,o){var i=e.apply(t,r);function a(e){f(i,n,o,a,u,"next",e)}function u(e){f(i,n,o,a,u,"throw",e)}a(void 0)})},function(){return t.apply(this,arguments)})})}return o.d(i,{default:()=>d}),i.default})());
@@ -1,11 +1,13 @@
1
- import { useEffect, useRef } from 'react'
1
+ import { useEffect, useRef, useState } from 'react'
2
2
  import { createMenu } from './createMenu.js'
3
3
  import { attachPluginStateRef } from '../registry/isVisibleWhen.js'
4
+ import { updateUrl } from './updateUrl.js'
4
5
 
5
6
  // additional possible params here are: appState, mapProvider,
6
7
  export function MenuInit ({ pluginConfig, pluginState, mapState, services }) {
7
8
  const { dispatch } = pluginState
8
9
  const { eventBus } = services
10
+ const [urlParsed, setUrlParsed] = useState(false)
9
11
 
10
12
  const pluginStateRef = useRef(pluginState)
11
13
  pluginStateRef.current = pluginState
@@ -16,9 +18,19 @@ export function MenuInit ({ pluginConfig, pluginState, mapState, services }) {
16
18
  }
17
19
  attachPluginStateRef(pluginStateRef)
18
20
  const { menu } = pluginConfig
19
- return createMenu({ menu, eventBus, dispatch, pluginStateRef })
21
+ // createMenu parses the url and combines the url parameters with the dataset defaults
22
+ // that are passed to the plugin as 'menu: {...}'
23
+ const teardown = createMenu({ menu, eventBus, dispatch, pluginStateRef })
24
+ setUrlParsed(true)
25
+ return teardown
20
26
  }, [mapState.isMapReady])
21
27
 
22
28
  // Notify any plugins, that are listening, to the menu's state change
23
- useEffect(() => eventBus.emit('menu:changed', pluginState.menuState), [pluginState.menuState])
29
+ // and update the url to reflect the new menu state
30
+ useEffect(() => {
31
+ eventBus.emit('menu:changed', pluginState.menuState)
32
+ if (urlParsed) { // Don't update the url until we have 1st parsed the url and initialised the menu
33
+ updateUrl(pluginState)
34
+ }
35
+ }, [pluginState.menuState])
24
36
  }
@@ -1,11 +1,16 @@
1
1
  import { render } from '@testing-library/react'
2
2
  import { MenuInit } from './MenuInit.jsx'
3
3
  import { createMenu } from './createMenu.js'
4
+ import { updateUrl } from './updateUrl.js'
4
5
 
5
6
  jest.mock('./createMenu.js', () => ({
6
7
  createMenu: jest.fn()
7
8
  }))
8
9
 
10
+ jest.mock('./updateUrl.js', () => ({
11
+ updateUrl: jest.fn()
12
+ }))
13
+
9
14
  const mockRemove = jest.fn()
10
15
  const mockDispatch = jest.fn()
11
16
  const eventBus = { on: jest.fn(), off: jest.fn(), emit: jest.fn(), emitWhenRequested: jest.fn() }
@@ -47,4 +52,24 @@ describe('MenuInit', () => {
47
52
  rerender(<MenuInit mapState={{ isMapReady: true }} services={services} pluginState={pluginState} pluginConfig={pluginConfig} />)
48
53
  expect(createMenu).toHaveBeenCalledTimes(1)
49
54
  })
55
+
56
+ it('emits menu:changed with the current menu state', () => {
57
+ const menuState = { datasets: 'floodZones' }
58
+ render(<MenuInit mapState={{ isMapReady: true }} services={services} pluginState={{ ...pluginState, menuState }} pluginConfig={pluginConfig} />)
59
+ expect(eventBus.emit).toHaveBeenCalledWith('menu:changed', menuState)
60
+ })
61
+
62
+ it('does not update the url before the url has been parsed', () => {
63
+ render(<MenuInit mapState={{ isMapReady: false }} services={services} pluginState={pluginState} pluginConfig={pluginConfig} />)
64
+ expect(updateUrl).not.toHaveBeenCalled()
65
+ })
66
+
67
+ it('updates the url when the menu state changes after the url has been parsed', () => {
68
+ const { rerender } = render(<MenuInit mapState={{ isMapReady: true }} services={services} pluginState={pluginState} pluginConfig={pluginConfig} />)
69
+ expect(updateUrl).not.toHaveBeenCalled()
70
+
71
+ const changedState = { ...pluginState, menuState: { datasets: 'coastalErosion' } }
72
+ rerender(<MenuInit mapState={{ isMapReady: true }} services={services} pluginState={changedState} pluginConfig={pluginConfig} />)
73
+ expect(updateUrl).toHaveBeenCalledWith(changedState)
74
+ })
50
75
  })
@@ -1,7 +1,9 @@
1
1
  import { setDatasetRegistry } from '../registry/getDatasetRegistry.js'
2
+ import { buildMenuState } from '../reducers/menuStateReducer.js'
2
3
 
3
4
  export const createMenu = ({ menu, eventBus, dispatch, pluginStateRef }) => {
4
- dispatch({ type: 'SET_MENU', payload: { menu } })
5
+ const menuState = buildMenuState(menu)
6
+ dispatch({ type: 'SET_MENU', payload: { menu, menuState } })
5
7
  // Request a handle on the datasetsRegistry singleton, so that the menu plugin can access it when needed
6
8
  eventBus.requestOnce('datasets:registry', setDatasetRegistry)
7
9
  // add a listener for the menu:state event, which will be emitted whenever requested by other plugins,
@@ -14,24 +14,39 @@ const makeEventBus = () => ({
14
14
  })
15
15
 
16
16
  describe('createMenu', () => {
17
- it('dispatches SET_MENU with the menu', () => {
17
+ const menu = [{ id: 'datasets', type: 'radio', value: 'floodZones' }]
18
+
19
+ it('dispatches SET_MENU with the menu and the built menu state', () => {
18
20
  const eventBus = makeEventBus()
19
21
  const dispatch = jest.fn()
20
- const menu = [{ id: 'layer1' }]
21
22
  createMenu({ menu, eventBus, dispatch, pluginStateRef: {} })
22
- expect(dispatch).toHaveBeenCalledWith({ type: 'SET_MENU', payload: { menu } })
23
+ expect(dispatch).toHaveBeenCalledWith({
24
+ type: 'SET_MENU',
25
+ payload: { menu, menuState: { datasets: 'floodZones' } }
26
+ })
27
+ })
28
+
29
+ it('builds the menu state from the URL search params', () => {
30
+ window.history.replaceState({}, '', '?datasets=other')
31
+ const dispatch = jest.fn()
32
+ createMenu({ menu, eventBus: makeEventBus(), dispatch, pluginStateRef: {} })
33
+ expect(dispatch).toHaveBeenCalledWith({
34
+ type: 'SET_MENU',
35
+ payload: { menu, menuState: { datasets: 'other' } }
36
+ })
37
+ window.history.replaceState({}, '', window.location.pathname)
23
38
  })
24
39
 
25
40
  it('calls requestOnce for the datasets registry', () => {
26
41
  const eventBus = makeEventBus()
27
- createMenu({ eventBus, dispatch: jest.fn(), pluginStateRef: {} })
42
+ createMenu({ menu, eventBus, dispatch: jest.fn(), pluginStateRef: {} })
28
43
  expect(eventBus.requestOnce).toHaveBeenCalledWith('datasets:registry', setDatasetRegistry)
29
44
  })
30
45
 
31
46
  it('calls emitWhenRequested for menu:state', () => {
32
47
  const eventBus = makeEventBus()
33
48
  const pluginStateRef = { current: {} }
34
- createMenu({ eventBus, dispatch: jest.fn(), pluginStateRef })
49
+ createMenu({ menu, eventBus, dispatch: jest.fn(), pluginStateRef })
35
50
  expect(eventBus.emitWhenRequested).toHaveBeenCalledWith('menu:state', pluginStateRef)
36
51
  })
37
52
  })
@@ -0,0 +1,44 @@
1
+ import { isVisibleWhen } from '../registry/isVisibleWhen.js'
2
+
3
+ const _setRadioParam = (item, menuState, searchParams) => {
4
+ const { id: paramId } = item
5
+ const paramValue = menuState[paramId]
6
+ searchParams.set(paramId, paramValue)
7
+ }
8
+
9
+ const _setCheckBoxParameters = (item, menuState, searchParams) => {
10
+ const { id: paramId, items: checkboxes } = item
11
+ const paramValues = []
12
+ checkboxes.forEach(subItem => {
13
+ const { id: checkBoxId } = subItem
14
+ const checked = menuState[checkBoxId]
15
+ if (checked) {
16
+ paramValues.push(checkBoxId)
17
+ }
18
+ })
19
+ if (paramValues.length) {
20
+ searchParams.set(paramId, paramValues)
21
+ } else {
22
+ searchParams.delete(paramId)
23
+ }
24
+ }
25
+
26
+ export const updateUrl = (pluginState) => {
27
+ const url = new URL(window.location.href)
28
+ const { searchParams } = url
29
+ const { menu, menuState } = pluginState
30
+ menu.forEach(item => {
31
+ const { id: paramId, visibleWhen, type } = item
32
+ if (!isVisibleWhen(visibleWhen)) {
33
+ searchParams.delete(paramId)
34
+ return
35
+ }
36
+ if (type === 'radio') {
37
+ _setRadioParam(item, menuState, searchParams)
38
+ } else {
39
+ _setCheckBoxParameters(item, menuState, searchParams)
40
+ }
41
+ })
42
+ url.search = decodeURIComponent(url.search)
43
+ window.history.replaceState({}, '', url.toString())
44
+ }
@@ -0,0 +1,91 @@
1
+ import { updateUrl } from './updateUrl.js'
2
+ import { attachPluginStateRef } from '../registry/isVisibleWhen.js'
3
+
4
+ const setSearch = (search) => {
5
+ window.history.replaceState({}, '', search || window.location.pathname)
6
+ }
7
+
8
+ const currentSearch = () => new URL(window.location.href).search
9
+
10
+ beforeEach(() => {
11
+ setSearch('')
12
+ attachPluginStateRef({})
13
+ })
14
+
15
+ afterAll(() => {
16
+ setSearch('')
17
+ })
18
+
19
+ describe('updateUrl', () => {
20
+ it('sets the search param for a radio group', () => {
21
+ const pluginState = {
22
+ menu: [{ id: 'datasets', type: 'radio' }],
23
+ menuState: { datasets: 'floodZones' }
24
+ }
25
+ updateUrl(pluginState)
26
+ expect(currentSearch()).toBe('?datasets=floodZones')
27
+ })
28
+
29
+ it('sets a comma separated search param for the checked checkboxes', () => {
30
+ const pluginState = {
31
+ menu: [{ id: 'layers', items: [{ id: 'flood' }, { id: 'erosion' }, { id: 'coastal' }] }],
32
+ menuState: { flood: true, erosion: false, coastal: true }
33
+ }
34
+ updateUrl(pluginState)
35
+ expect(currentSearch()).toBe('?layers=flood,coastal')
36
+ })
37
+
38
+ it('removes the search param when no checkboxes are checked', () => {
39
+ setSearch('?layers=flood')
40
+ const pluginState = {
41
+ menu: [{ id: 'layers', items: [{ id: 'flood' }] }],
42
+ menuState: { flood: false }
43
+ }
44
+ updateUrl(pluginState)
45
+ expect(currentSearch()).toBe('')
46
+ })
47
+
48
+ it('removes the search param for a group that is not visible', () => {
49
+ setSearch('?datasets=floodZones')
50
+ const pluginState = {
51
+ menu: [{ id: 'datasets', type: 'radio', visibleWhen: false }],
52
+ menuState: { datasets: 'floodZones' }
53
+ }
54
+ updateUrl(pluginState)
55
+ expect(currentSearch()).toBe('')
56
+ })
57
+
58
+ it('honours a visibleWhen menu condition against the current menu state', () => {
59
+ const menuState = { datasets: 'coastalErosion', timeframe: '2050' }
60
+ attachPluginStateRef({ current: { menuState } })
61
+ const pluginState = {
62
+ menu: [
63
+ { id: 'datasets', type: 'radio' },
64
+ { id: 'timeframe', type: 'radio', visibleWhen: { menu: { datasets: ['floodZones'] } } }
65
+ ],
66
+ menuState
67
+ }
68
+ updateUrl(pluginState)
69
+ expect(currentSearch()).toBe('?datasets=coastalErosion')
70
+ })
71
+
72
+ it('leaves unrelated search params untouched', () => {
73
+ setSearch('?zoom=12')
74
+ const pluginState = {
75
+ menu: [{ id: 'datasets', type: 'radio' }],
76
+ menuState: { datasets: 'floodZones' }
77
+ }
78
+ updateUrl(pluginState)
79
+ expect(currentSearch()).toBe('?zoom=12&datasets=floodZones')
80
+ })
81
+
82
+ it('replaces the history entry rather than pushing a new one', () => {
83
+ const replaceState = jest.spyOn(window.history, 'replaceState')
84
+ const pushState = jest.spyOn(window.history, 'pushState')
85
+ updateUrl({ menu: [{ id: 'datasets', type: 'radio' }], menuState: { datasets: 'floodZones' } })
86
+ expect(replaceState).toHaveBeenCalled()
87
+ expect(pushState).not.toHaveBeenCalled()
88
+ replaceState.mockRestore()
89
+ pushState.mockRestore()
90
+ })
91
+ })
@@ -1,8 +1,26 @@
1
+ // This reducer builds the initial state of the menu based on the URL
2
+ // and the default configuration that is provided for the plugin
1
3
  export const buildMenuState = (menu) => {
4
+ const url = new URL(window.location.href)
5
+ const { searchParams } = url
6
+
2
7
  const menuState = {}
3
8
  menu.forEach(menuGroup => {
9
+ const searchParamValue = searchParams.get(menuGroup.id)
4
10
  if (menuGroup.type === 'radio') {
5
- menuState[menuGroup.id] = menuGroup.value || menuGroup.items?.[0].value
11
+ menuState[menuGroup.id] = searchParamValue || menuGroup.value || menuGroup.items?.[0].value
12
+ } else { // checkBox
13
+ const { items: configuredCheckboxes } = menuGroup
14
+
15
+ // Loop through the checkbox items and set their state based on the URL or default checked value
16
+ configuredCheckboxes.forEach(checkbox => {
17
+ const { id: checkBoxId, checked: checkedInConfig } = checkbox
18
+ // it should be checked if it is set to be checked in the config,
19
+ // unless the URL specifies some values for this group
20
+ // but not this specific one.
21
+ const shouldBeChecked = searchParamValue ? searchParamValue.includes(checkBoxId) : checkedInConfig
22
+ menuState[checkBoxId] = shouldBeChecked
23
+ })
6
24
  }
7
25
  })
8
26
  return menuState
@@ -1,38 +1,71 @@
1
1
  import { buildMenuState } from './menuStateReducer.js'
2
2
 
3
3
  describe('buildMenuState', () => {
4
+ const setSearch = (search) => {
5
+ window.history.replaceState({}, '', search || window.location.pathname)
6
+ }
7
+
8
+ afterEach(() => {
9
+ setSearch('')
10
+ })
11
+
4
12
  it('returns an empty object for an empty menu', () => {
5
13
  expect(buildMenuState([])).toEqual({})
6
14
  })
7
15
 
8
- it('ignores non-radio menu groups', () => {
9
- const menu = [{ id: 'layer', type: 'checkbox', value: 'a' }]
10
- expect(buildMenuState(menu)).toEqual({})
11
- })
16
+ describe('radio groups', () => {
17
+ it('uses the explicit value when set', () => {
18
+ const menu = [{ id: 'datasets', type: 'radio', value: 'floodZones', items: [{ value: 'other' }] }]
19
+ expect(buildMenuState(menu)).toEqual({ datasets: 'floodZones' })
20
+ })
12
21
 
13
- it('uses the explicit value when set', () => {
14
- const menu = [{ id: 'datasets', type: 'radio', value: 'floodZones', items: [{ value: 'other' }] }]
15
- expect(buildMenuState(menu)).toEqual({ datasets: 'floodZones' })
16
- })
22
+ it('falls back to the first item value when no value is set', () => {
23
+ const menu = [{ id: 'datasets', type: 'radio', items: [{ value: 'floodZones' }, { value: 'other' }] }]
24
+ expect(buildMenuState(menu)).toEqual({ datasets: 'floodZones' })
25
+ })
26
+
27
+ it('prefers the URL search param over the configured value', () => {
28
+ setSearch('?datasets=other')
29
+ const menu = [{ id: 'datasets', type: 'radio', value: 'floodZones', items: [{ value: 'other' }] }]
30
+ expect(buildMenuState(menu)).toEqual({ datasets: 'other' })
31
+ })
17
32
 
18
- it('falls back to the first item value when no value is set', () => {
19
- const menu = [{ id: 'datasets', type: 'radio', items: [{ value: 'floodZones' }, { value: 'other' }] }]
20
- expect(buildMenuState(menu)).toEqual({ datasets: 'floodZones' })
33
+ it('handles multiple radio groups', () => {
34
+ const menu = [
35
+ { id: 'datasets', type: 'radio', value: 'floodZones' },
36
+ { id: 'timeframe', type: 'radio', items: [{ value: 'presentDay' }] }
37
+ ]
38
+ expect(buildMenuState(menu)).toEqual({ datasets: 'floodZones', timeframe: 'presentDay' })
39
+ })
21
40
  })
22
41
 
23
- it('handles multiple radio groups', () => {
24
- const menu = [
25
- { id: 'datasets', type: 'radio', value: 'floodZones' },
26
- { id: 'timeframe', type: 'radio', items: [{ value: 'presentDay' }] }
27
- ]
28
- expect(buildMenuState(menu)).toEqual({ datasets: 'floodZones', timeframe: 'presentDay' })
42
+ describe('checkbox groups', () => {
43
+ const checkboxMenu = [{
44
+ id: 'layers',
45
+ type: 'checkbox',
46
+ items: [{ id: 'flood', checked: true }, { id: 'erosion', checked: false }]
47
+ }]
48
+
49
+ it('uses the configured checked values when the URL has no param for the group', () => {
50
+ expect(buildMenuState(checkboxMenu)).toEqual({ flood: true, erosion: false })
51
+ })
52
+
53
+ it('uses the URL param to determine which checkboxes are checked', () => {
54
+ setSearch('?layers=erosion')
55
+ expect(buildMenuState(checkboxMenu)).toEqual({ flood: false, erosion: true })
56
+ })
57
+
58
+ it('supports multiple checked values in the URL param', () => {
59
+ setSearch('?layers=flood,erosion')
60
+ expect(buildMenuState(checkboxMenu)).toEqual({ flood: true, erosion: true })
61
+ })
29
62
  })
30
63
 
31
- it('mixes radio and non-radio groups, only including radios', () => {
64
+ it('combines radio and checkbox groups', () => {
32
65
  const menu = [
33
- { id: 'layer', type: 'checkbox', value: 'a' },
66
+ { id: 'layers', type: 'checkbox', items: [{ id: 'flood', checked: true }] },
34
67
  { id: 'datasets', type: 'radio', value: 'floodZones' }
35
68
  ]
36
- expect(buildMenuState(menu)).toEqual({ datasets: 'floodZones' })
69
+ expect(buildMenuState(menu)).toEqual({ flood: true, datasets: 'floodZones' })
37
70
  })
38
71
  })
@@ -1,7 +1,4 @@
1
- import { buildMenuState } from './menuStateReducer.js'
2
-
3
1
  const initialState = {
4
- actionsArray: [],
5
2
  menu: [],
6
3
  menuState: {}
7
4
  }
@@ -14,9 +11,7 @@ const updateMenuState = (state, payload) => {
14
11
  }
15
12
 
16
13
  const setMenu = (state, payload) => {
17
- const { menu } = payload
18
- // build the initial menuState for radios from the menu
19
- const menuState = buildMenuState(menu)
14
+ const { menu, menuState } = payload
20
15
  return {
21
16
  ...state,
22
17
  menu,