@defra/interactive-map 0.0.15-alpha → 0.0.17-alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (263) hide show
  1. package/assets/css/docusaurus.css +104 -0
  2. package/assets/images/favicon.svg +1 -0
  3. package/assets/images/hero.png +0 -0
  4. package/assets/images/slot-map.svg +264 -0
  5. package/dist/css/index.css +1 -1
  6. package/dist/esm/im-core.js +1 -1
  7. package/dist/esm/im-shell.js +1 -1
  8. package/dist/umd/im-core.js +1 -1
  9. package/dist/umd/index.js +1 -1
  10. package/docs/api/slots.md +90 -6
  11. package/docs/api.md +4 -4
  12. package/docs/architecture.md +3 -1
  13. package/docs/{demo.mdx → examples.mdx} +1 -1
  14. package/docs/getting-started.md +5 -4
  15. package/docs/index.mdx +42 -0
  16. package/docs/plugins/datasets.md +561 -0
  17. package/docs/plugins/interact.md +176 -55
  18. package/docs/plugins/map-styles.md +64 -7
  19. package/docs/plugins/search.md +207 -63
  20. package/docs/plugins.md +8 -16
  21. package/docusaurus.config.cjs +34 -34
  22. package/jest.setup.js +1 -1
  23. package/package.json +6 -5
  24. package/plugins/beta/datasets/dist/css/index.css +85 -15
  25. package/plugins/beta/datasets/dist/esm/im-datasets-plugin.js +1 -1
  26. package/plugins/beta/datasets/dist/umd/im-datasets-plugin.js +1 -1
  27. package/plugins/beta/datasets/dist/umd/index.js +1 -1
  28. package/plugins/beta/datasets/src/DatasetsInit.jsx +24 -9
  29. package/plugins/beta/datasets/src/adapters/maplibre/index.js +18 -0
  30. package/plugins/beta/datasets/src/adapters/maplibre/layerBuilders.js +113 -0
  31. package/plugins/beta/datasets/src/adapters/maplibre/layerIds.js +69 -0
  32. package/plugins/beta/datasets/src/adapters/maplibre/maplibreLayerAdapter.js +338 -0
  33. package/plugins/beta/datasets/src/adapters/maplibre/patternRegistry.js +48 -0
  34. package/plugins/beta/datasets/src/api/addDataset.js +3 -9
  35. package/plugins/beta/datasets/src/api/getOpacity.js +17 -0
  36. package/plugins/beta/datasets/src/api/getStyle.js +13 -0
  37. package/plugins/beta/datasets/src/api/removeDataset.js +3 -45
  38. package/plugins/beta/datasets/src/api/setData.js +8 -0
  39. package/plugins/beta/datasets/src/api/setDatasetVisibility.js +37 -0
  40. package/plugins/beta/datasets/src/api/setFeatureVisibility.js +22 -0
  41. package/plugins/beta/datasets/src/api/setOpacity.js +29 -0
  42. package/plugins/beta/datasets/src/api/setStyle.js +22 -0
  43. package/plugins/beta/datasets/src/datasets.js +33 -59
  44. package/plugins/beta/datasets/src/defaults.js +43 -9
  45. package/plugins/beta/datasets/src/fetch/createDynamicSource.js +39 -30
  46. package/plugins/beta/datasets/src/fetch/fetchGeoJSON.js +2 -2
  47. package/plugins/beta/datasets/src/manifest.js +27 -19
  48. package/plugins/beta/datasets/src/panels/Key.jsx +129 -49
  49. package/plugins/beta/datasets/src/panels/Key.module.scss +48 -9
  50. package/plugins/beta/datasets/src/panels/Layers.jsx +131 -29
  51. package/plugins/beta/datasets/src/panels/Layers.module.scss +50 -8
  52. package/plugins/beta/datasets/src/reducer.js +128 -9
  53. package/plugins/beta/datasets/src/styles/patterns.js +157 -0
  54. package/plugins/beta/datasets/src/utils/bbox.js +8 -6
  55. package/plugins/beta/datasets/src/utils/filters.js +5 -2
  56. package/plugins/beta/datasets/src/utils/mergeSublayer.js +78 -0
  57. package/plugins/beta/draw-es/dist/esm/im-draw-es-plugin.js +1 -1
  58. package/plugins/beta/draw-es/src/DrawInit.jsx +16 -16
  59. package/plugins/beta/draw-es/src/api/addFeature.js +3 -3
  60. package/plugins/beta/draw-es/src/api/deleteFeature.js +3 -3
  61. package/plugins/beta/draw-es/src/api/editFeature.js +3 -3
  62. package/plugins/beta/draw-es/src/api/newPolygon.js +3 -3
  63. package/plugins/beta/draw-es/src/events.js +52 -20
  64. package/plugins/beta/draw-es/src/events.test.js +301 -0
  65. package/plugins/beta/draw-es/src/graphic.js +1 -1
  66. package/plugins/beta/draw-es/src/manifest.js +4 -4
  67. package/plugins/beta/draw-es/src/reducer.js +1 -1
  68. package/plugins/beta/draw-es/src/sketchViewModel.js +1 -1
  69. package/plugins/beta/draw-ml/dist/css/index.css +1 -1
  70. package/plugins/beta/draw-ml/dist/esm/im-draw-ml-plugin.js +1 -1
  71. package/plugins/beta/draw-ml/dist/umd/im-draw-ml-plugin.js +1 -1
  72. package/plugins/beta/draw-ml/src/DrawInit.jsx +49 -52
  73. package/plugins/beta/draw-ml/src/api/deleteFeature.js +1 -1
  74. package/plugins/beta/draw-ml/src/api/editFeature.js +8 -5
  75. package/plugins/beta/draw-ml/src/api/newLine.js +0 -1
  76. package/plugins/beta/draw-ml/src/api/newPolygon.js +0 -1
  77. package/plugins/beta/draw-ml/src/api/split.js +4 -4
  78. package/plugins/beta/draw-ml/src/defaults.js +1 -1
  79. package/plugins/beta/draw-ml/src/draw.scss +0 -7
  80. package/plugins/beta/draw-ml/src/events.js +8 -6
  81. package/plugins/beta/draw-ml/src/manifest.js +29 -29
  82. package/plugins/beta/draw-ml/src/mapboxDraw.js +1 -1
  83. package/plugins/beta/draw-ml/src/mapboxSnap.js +17 -18
  84. package/plugins/beta/draw-ml/src/modes/createDrawMode.js +31 -31
  85. package/plugins/beta/draw-ml/src/modes/disabledMode.js +1 -1
  86. package/plugins/beta/draw-ml/src/modes/editVertex/touchHandlers.js +11 -11
  87. package/plugins/beta/draw-ml/src/modes/editVertex/undoHandlers.js +7 -7
  88. package/plugins/beta/draw-ml/src/modes/editVertex/vertexOperations.js +8 -8
  89. package/plugins/beta/draw-ml/src/modes/editVertex/vertexQueries.js +7 -7
  90. package/plugins/beta/draw-ml/src/modes/editVertexMode.js +32 -24
  91. package/plugins/beta/draw-ml/src/reducer.js +1 -1
  92. package/plugins/beta/draw-ml/src/undoStack.js +4 -4
  93. package/plugins/beta/draw-ml/src/utils/snapHelpers.js +12 -12
  94. package/plugins/beta/draw-ml/src/utils/spatial.js +11 -11
  95. package/plugins/beta/frame/dist/esm/im-frame-plugin.js +1 -1
  96. package/plugins/beta/frame/dist/umd/im-frame-plugin.js +1 -1
  97. package/plugins/beta/frame/src/Frame.jsx +9 -9
  98. package/plugins/beta/frame/src/FrameInit.jsx +4 -4
  99. package/plugins/beta/frame/src/api/addFrame.js +1 -1
  100. package/plugins/beta/frame/src/api/editFeature.js +1 -1
  101. package/plugins/beta/frame/src/config.js +1 -1
  102. package/plugins/beta/frame/src/manifest.js +3 -3
  103. package/plugins/beta/frame/src/reducer.js +1 -1
  104. package/plugins/beta/frame/src/utils.js +1 -1
  105. package/plugins/beta/map-styles/dist/esm/im-map-styles-plugin.js +1 -1
  106. package/plugins/beta/map-styles/dist/umd/im-map-styles-plugin.js +1 -1
  107. package/plugins/beta/map-styles/src/MapStyles.jsx +18 -18
  108. package/plugins/beta/map-styles/src/manifest.js +1 -1
  109. package/plugins/beta/scale-bar/dist/css/index.css +1 -1
  110. package/plugins/beta/scale-bar/dist/esm/im-scale-bar-plugin.js +1 -1
  111. package/plugins/beta/scale-bar/dist/umd/im-scale-bar-plugin.js +1 -1
  112. package/plugins/beta/scale-bar/src/ScaleBar.jsx +5 -5
  113. package/plugins/beta/scale-bar/src/index.test.js +3 -3
  114. package/plugins/beta/scale-bar/src/manifest.js +3 -3
  115. package/plugins/beta/scale-bar/src/scaleBar.scss +2 -1
  116. package/plugins/beta/use-location/src/UseLocation.jsx +1 -1
  117. package/plugins/beta/use-location/src/defaults.js +1 -1
  118. package/plugins/beta/use-location/src/events.js +3 -3
  119. package/plugins/interact/dist/css/index.css +1 -1
  120. package/plugins/interact/dist/esm/im-interact-plugin.js +1 -1
  121. package/plugins/interact/dist/umd/im-interact-plugin.js +1 -1
  122. package/plugins/interact/src/InteractInit.jsx +1 -2
  123. package/plugins/interact/src/api/enable.js +8 -5
  124. package/plugins/interact/src/api/enable.test.js +2 -2
  125. package/plugins/interact/src/api/selectFeature.js +4 -4
  126. package/plugins/interact/src/api/unselectFeature.js +5 -5
  127. package/plugins/interact/src/defaults.js +0 -1
  128. package/plugins/interact/src/events.test.js +15 -15
  129. package/plugins/interact/src/hooks/useHighlightSync.js +1 -1
  130. package/plugins/interact/src/hooks/useInteractionHandlers.js +2 -2
  131. package/plugins/interact/src/hooks/useInteractionHandlers.test.js +5 -5
  132. package/plugins/interact/src/interact.scss +0 -7
  133. package/plugins/interact/src/manifest.js +15 -19
  134. package/plugins/interact/src/manifest.test.js +6 -5
  135. package/plugins/interact/src/reducer.js +3 -3
  136. package/plugins/interact/src/reducer.test.js +0 -1
  137. package/plugins/interact/src/utils/spatial.js +10 -10
  138. package/plugins/interact/src/utils/spatial.test.js +14 -14
  139. package/plugins/search/dist/css/index.css +1 -1
  140. package/plugins/search/dist/esm/im-search-plugin.js +1 -1
  141. package/plugins/search/dist/esm/index.js +1 -1
  142. package/plugins/search/dist/umd/im-search-plugin.js +1 -1
  143. package/plugins/search/dist/umd/index.js +1 -1
  144. package/plugins/search/src/Search.jsx +7 -6
  145. package/plugins/search/src/Search.test.jsx +23 -23
  146. package/plugins/search/src/components/CloseButton/CloseButton.jsx +15 -15
  147. package/plugins/search/src/components/CloseButton/CloseButton.test.jsx +2 -2
  148. package/plugins/search/src/components/Form/Form.jsx +14 -14
  149. package/plugins/search/src/components/Form/Form.module.scss +2 -1
  150. package/plugins/search/src/components/Form/Form.test.jsx +11 -11
  151. package/plugins/search/src/components/OpenButton/OpenButton.jsx +16 -15
  152. package/plugins/search/src/components/OpenButton/OpenButton.test.jsx +6 -2
  153. package/plugins/search/src/components/SubmitButton/SubmitButton.jsx +15 -15
  154. package/plugins/search/src/components/Suggestions/Suggestions.jsx +6 -6
  155. package/plugins/search/src/components/Suggestions/Suggestions.test.jsx +4 -4
  156. package/plugins/search/src/datasets.js +12 -13
  157. package/plugins/search/src/datasets.test.js +1 -1
  158. package/plugins/search/src/defaults.js +1 -1
  159. package/plugins/search/src/events/fetchSuggestions.js +3 -3
  160. package/plugins/search/src/events/fetchSuggestions.test.js +1 -1
  161. package/plugins/search/src/events/formHandlers.js +3 -3
  162. package/plugins/search/src/events/formHandlers.test.js +1 -1
  163. package/plugins/search/src/events/index.js +2 -2
  164. package/plugins/search/src/events/index.test.js +2 -2
  165. package/plugins/search/src/events/inputHandlers.js +4 -4
  166. package/plugins/search/src/events/inputHandlers.test.js +1 -1
  167. package/plugins/search/src/events/suggestionHandlers.js +2 -2
  168. package/plugins/search/src/events/suggestionHandlers.test.js +1 -1
  169. package/plugins/search/src/index.js +2 -1
  170. package/plugins/search/src/index.test.js +3 -3
  171. package/plugins/search/src/manifest.js +6 -4
  172. package/plugins/search/src/reducer.js +1 -2
  173. package/plugins/search/src/reducer.test.js +2 -2
  174. package/plugins/search/src/search.scss +10 -3
  175. package/plugins/search/src/utils/parseOsNamesResults.js +1 -2
  176. package/plugins/search/src/utils/parseOsNamesResults.test.js +2 -2
  177. package/plugins/search/src/utils/updateMap.js +1 -1
  178. package/plugins/search/src/utils/updateMap.test.js +5 -5
  179. package/providers/beta/esri/dist/esm/im-esri-provider.js +1 -1
  180. package/providers/beta/esri/src/esriProvider.js +5 -5
  181. package/providers/beta/esri/src/utils/coords.js +1 -1
  182. package/providers/beta/esri/src/utils/esriFixes.js +1 -1
  183. package/providers/beta/esri/src/utils/query.js +4 -4
  184. package/providers/beta/esri/src/utils/spatial.js +1 -2
  185. package/providers/beta/esri/src/utils/spatial.test.js +4 -1
  186. package/providers/beta/open-names/src/utils/mapToLocationModel.test.js +1 -1
  187. package/providers/maplibre/dist/esm/im-maplibre-provider.js +1 -1
  188. package/providers/maplibre/dist/umd/im-maplibre-framework.js +1 -1
  189. package/providers/maplibre/dist/umd/im-maplibre-framework.js.LICENSE.txt +1 -1
  190. package/providers/maplibre/dist/umd/im-maplibre-provider.js +1 -1
  191. package/providers/maplibre/src/appEvents.test.js +1 -1
  192. package/providers/maplibre/src/index.js +1 -1
  193. package/providers/maplibre/src/index.test.js +3 -5
  194. package/providers/maplibre/src/mapEvents.test.js +15 -5
  195. package/providers/maplibre/src/maplibreProvider.test.js +6 -2
  196. package/providers/maplibre/src/utils/calculateLinearTextSize.js +4 -4
  197. package/providers/maplibre/src/utils/calculateLinearTextSize.test.js +3 -3
  198. package/providers/maplibre/src/utils/detectWebgl.test.js +1 -1
  199. package/providers/maplibre/src/utils/highlightFeatures.js +3 -2
  200. package/providers/maplibre/src/utils/highlightFeatures.test.js +13 -6
  201. package/providers/maplibre/src/utils/labels.js +19 -20
  202. package/providers/maplibre/src/utils/labels.test.js +15 -13
  203. package/providers/maplibre/src/utils/maplibreFixes.test.js +1 -1
  204. package/providers/maplibre/src/utils/queryFeatures.js +6 -6
  205. package/providers/maplibre/src/utils/queryFeatures.test.js +13 -13
  206. package/providers/maplibre/src/utils/spatial.js +0 -1
  207. package/providers/maplibre/src/utils/spatial.test.js +26 -27
  208. package/src/App/components/Actions/Actions.jsx +2 -2
  209. package/src/App/components/Actions/Actions.module.scss +0 -7
  210. package/src/App/components/Actions/Actions.test.jsx +1 -1
  211. package/src/App/components/Icon/Icon.jsx +3 -2
  212. package/src/App/components/Icon/Icon.module.scss +4 -0
  213. package/src/App/components/Icon/Icon.test.jsx +43 -4
  214. package/src/App/components/MapButton/MapButton.jsx +42 -17
  215. package/src/App/components/MapButton/MapButton.module.scss +4 -13
  216. package/src/App/components/MapButton/MapButton.test.jsx +27 -3
  217. package/src/App/components/PopupMenu/PopupMenu.jsx +51 -274
  218. package/src/App/components/PopupMenu/PopupMenu.module.scss +14 -7
  219. package/src/App/components/PopupMenu/PopupMenu.test.jsx +70 -1
  220. package/src/App/components/PopupMenu/usePopupMenu.js +258 -0
  221. package/src/App/hooks/useButtonStateEvaluator.js +12 -2
  222. package/src/App/hooks/useButtonStateEvaluator.test.js +38 -4
  223. package/src/App/hooks/useInterfaceAPI.js +6 -0
  224. package/src/App/hooks/useLayoutMeasurements.js +84 -18
  225. package/src/App/hooks/useLayoutMeasurements.test.js +124 -17
  226. package/src/App/layout/Layout.jsx +12 -7
  227. package/src/App/layout/Layout.test.jsx +2 -2
  228. package/src/App/layout/layout.module.scss +67 -29
  229. package/src/App/registry/pluginRegistry.js +17 -0
  230. package/src/App/registry/pluginRegistry.test.js +33 -0
  231. package/src/App/renderer/HtmlElementHost.jsx +2 -1
  232. package/src/App/renderer/HtmlElementHost.test.jsx +7 -7
  233. package/src/App/renderer/mapButtons.js +3 -2
  234. package/src/App/renderer/mapPanels.test.js +2 -2
  235. package/src/App/renderer/slotHelpers.js +2 -2
  236. package/src/App/renderer/slotHelpers.test.js +5 -5
  237. package/src/App/renderer/slots.js +9 -5
  238. package/src/App/store/AppProvider.jsx +3 -1
  239. package/src/App/store/AppProvider.test.jsx +1 -1
  240. package/src/App/store/ServiceProvider.jsx +3 -1
  241. package/src/App/store/appActionsMap.js +16 -0
  242. package/src/App/store/appActionsMap.test.js +27 -0
  243. package/src/App/store/appDispatchMiddleware.js +33 -1
  244. package/src/App/store/appDispatchMiddleware.test.js +250 -222
  245. package/src/App/store/appReducer.js +2 -0
  246. package/src/InteractiveMap/InteractiveMap.js +4 -0
  247. package/src/config/appConfig.js +7 -4
  248. package/src/config/events.js +28 -0
  249. package/src/scss/main.scss +1 -0
  250. package/src/scss/settings/_dimensions.scss +0 -1
  251. package/src/services/logger.js +6 -0
  252. package/src/services/logger.test.js +32 -0
  253. package/src/utils/getSafeZoneInset.js +9 -7
  254. package/src/utils/getSafeZoneInset.test.js +10 -10
  255. package/webpack.dev.mjs +23 -19
  256. package/docs/govuk-prototype.md +0 -23
  257. package/docs/index.md +0 -19
  258. package/plugins/beta/datasets/src/api/hideDataset.js +0 -14
  259. package/plugins/beta/datasets/src/api/hideFeatures.js +0 -41
  260. package/plugins/beta/datasets/src/api/showDataset.js +0 -14
  261. package/plugins/beta/datasets/src/api/showFeatures.js +0 -44
  262. package/plugins/beta/datasets/src/handleSetMapStyle.js +0 -54
  263. package/plugins/beta/datasets/src/mapLayers.js +0 -165
@@ -10,8 +10,9 @@ export const layoutSlots = Object.freeze({
10
10
  MIDDLE: 'middle',
11
11
  RIGHT_TOP: 'right-top',
12
12
  RIGHT_BOTTOM: 'right-bottom',
13
- FOOTER_RIGHT: 'footer-right',
14
- BOTTOM: 'bottom',
13
+ BOTTOM_LEFT: 'bottom-left',
14
+ BOTTOM_RIGHT: 'bottom-right',
15
+ DRAWER: 'drawer',
15
16
  ACTIONS: 'actions',
16
17
  MODAL: 'modal' // internal only
17
18
  })
@@ -22,8 +23,9 @@ export const allowedSlots = Object.freeze({
22
23
  layoutSlots.TOP_LEFT,
23
24
  layoutSlots.TOP_RIGHT,
24
25
  layoutSlots.MIDDLE,
25
- layoutSlots.FOOTER_RIGHT,
26
- layoutSlots.BOTTOM,
26
+ layoutSlots.RIGHT_BOTTOM,
27
+ layoutSlots.BOTTOM_RIGHT,
28
+ layoutSlots.DRAWER,
27
29
  layoutSlots.ACTIONS
28
30
  ],
29
31
  panel: [
@@ -34,7 +36,7 @@ export const allowedSlots = Object.freeze({
34
36
  layoutSlots.MIDDLE,
35
37
  layoutSlots.RIGHT_TOP,
36
38
  layoutSlots.RIGHT_BOTTOM,
37
- layoutSlots.BOTTOM, // Typicaly on mobile
39
+ layoutSlots.DRAWER, // Typically on mobile
38
40
  layoutSlots.MODAL // Internal only
39
41
  ],
40
42
  button: [
@@ -45,6 +47,8 @@ export const allowedSlots = Object.freeze({
45
47
  layoutSlots.LEFT_BOTTOM,
46
48
  layoutSlots.RIGHT_TOP,
47
49
  layoutSlots.RIGHT_BOTTOM,
50
+ layoutSlots.BOTTOM_LEFT,
51
+ layoutSlots.BOTTOM_RIGHT,
48
52
  layoutSlots.ACTIONS
49
53
  ]
50
54
  })
@@ -26,8 +26,10 @@ export const AppProvider = ({ options, children }) => {
26
26
  rightRef: useRef(null),
27
27
  rightTopRef: useRef(null),
28
28
  rightBottomRef: useRef(null),
29
+ drawerRef: useRef(null),
29
30
  bottomRef: useRef(null),
30
- footerRef: useRef(null),
31
+ bottomRightRef: useRef(null),
32
+ attributionsRef: useRef(null),
31
33
  actionsRef: useRef(null),
32
34
  bannerRef: useRef(null),
33
35
  modalRef: useRef(null),
@@ -110,7 +110,7 @@ describe('AppProvider', () => {
110
110
  expect(contextValue).toHaveProperty('mode')
111
111
  expect(contextValue).toHaveProperty('openPanels')
112
112
  expect(contextValue.layoutRefs).toHaveProperty('mainRef')
113
- expect(contextValue.layoutRefs).toHaveProperty('footerRef')
113
+ expect(contextValue.layoutRefs).toHaveProperty('bottomRef')
114
114
  })
115
115
 
116
116
  test('dispatch fallback uses options.panelRegistry.getPanelConfig() when state.panelConfig missing', () => {
@@ -5,6 +5,7 @@ import { createAnnouncer } from '../../services/announcer.js'
5
5
  import { reverseGeocode } from '../../services/reverseGeocode.js'
6
6
  import { useConfig } from '../store/configContext.js'
7
7
  import { closeApp } from '../../services/closeApp.js'
8
+ import { logger } from '../../services/logger.js'
8
9
 
9
10
  export const ServiceContext = createContext(null)
10
11
 
@@ -19,7 +20,8 @@ export const ServiceProvider = ({ eventBus, children }) => {
19
20
  events: EVENTS,
20
21
  eventBus,
21
22
  mapStatusRef,
22
- closeApp: () => closeApp(id, handleExitClick, eventBus)
23
+ closeApp: () => closeApp(id, handleExitClick, eventBus),
24
+ logger
23
25
  }), [announce])
24
26
 
25
27
  return (
@@ -152,6 +152,12 @@ const toggleHasExclusiveControl = (state, payload) => {
152
152
  }
153
153
  }
154
154
 
155
+ const setPluginsEvaluated = (state) =>
156
+ state.arePluginsEvaluated ? state : { ...state, arePluginsEvaluated: true }
157
+
158
+ const clearPluginsEvaluated = (state) =>
159
+ state.arePluginsEvaluated ? { ...state, arePluginsEvaluated: false } : state
160
+
155
161
  const setSafeZoneInset = (state, { safeZoneInset, syncMapPadding = true }) => {
156
162
  return shallowEqual(state.safeZoneInset, safeZoneInset)
157
163
  ? state
@@ -163,6 +169,13 @@ const setSafeZoneInset = (state, { safeZoneInset, syncMapPadding = true }) => {
163
169
  }
164
170
  }
165
171
 
172
+ const toggleAppVisible = (state, payload) => {
173
+ return {
174
+ ...state,
175
+ appVisible: payload
176
+ }
177
+ }
178
+
166
179
  const toggleButtonDisabled = (state, payload) => {
167
180
  const { id, isDisabled } = payload
168
181
  const updated = new Set(state.disabledButtons)
@@ -358,12 +371,15 @@ export const actionsMap = {
358
371
  SET_HYBRID_FULLSCREEN: setHybridFullscreen,
359
372
  SET_INTERFACE_TYPE: setInterfaceType,
360
373
  SET_MODE: setMode,
374
+ PLUGINS_EVALUATED: setPluginsEvaluated,
375
+ CLEAR_PLUGINS_EVALUATED: clearPluginsEvaluated,
361
376
  SET_SAFE_ZONE_INSET: setSafeZoneInset,
362
377
  REVERT_MODE: revertMode,
363
378
  OPEN_PANEL: openPanel,
364
379
  CLOSE_PANEL: closePanel,
365
380
  CLOSE_ALL_PANELS: closeAllPanels,
366
381
  RESTORE_PREVIOUS_PANELS: restorePreviousPanels,
382
+ TOGGLE_APP_VISIBLE: toggleAppVisible,
367
383
  TOGGLE_HAS_EXCLUSIVE_CONTROL: toggleHasExclusiveControl,
368
384
  TOGGLE_BUTTON_DISABLED: toggleButtonDisabled,
369
385
  TOGGLE_BUTTON_HIDDEN: toggleButtonHidden,
@@ -128,6 +128,26 @@ describe('actionsMap full coverage', () => {
128
128
  expect(result.hasExclusiveControl).toBe(true)
129
129
  })
130
130
 
131
+ test('PLUGINS_EVALUATED is no-op when arePluginsEvaluated already true', () => {
132
+ const s = { ...state, arePluginsEvaluated: true }
133
+ expect(actionsMap.PLUGINS_EVALUATED(s)).toBe(s)
134
+ })
135
+
136
+ test('PLUGINS_EVALUATED sets arePluginsEvaluated when false', () => {
137
+ const s = { ...state, arePluginsEvaluated: false }
138
+ expect(actionsMap.PLUGINS_EVALUATED(s).arePluginsEvaluated).toBe(true)
139
+ })
140
+
141
+ test('CLEAR_PLUGINS_EVALUATED clears arePluginsEvaluated when true', () => {
142
+ const s = { ...state, arePluginsEvaluated: true }
143
+ expect(actionsMap.CLEAR_PLUGINS_EVALUATED(s).arePluginsEvaluated).toBe(false)
144
+ })
145
+
146
+ test('CLEAR_PLUGINS_EVALUATED is no-op when arePluginsEvaluated already false', () => {
147
+ const s = { ...state, arePluginsEvaluated: false }
148
+ expect(actionsMap.CLEAR_PLUGINS_EVALUATED(s)).toBe(s)
149
+ })
150
+
131
151
  test('SET_SAFE_ZONE_INSET branch true/false', () => {
132
152
  shallowEqualModule.shallowEqual.mockReturnValueOnce(false)
133
153
  const res1 = actionsMap.SET_SAFE_ZONE_INSET(state, { safeZoneInset: { top: 10, bottom: 10 } })
@@ -152,6 +172,13 @@ describe('actionsMap full coverage', () => {
152
172
  expect(r2.hiddenButtons.has('btn3')).toBe(false)
153
173
  })
154
174
 
175
+ test('TOGGLE_APP_VISIBLE sets appVisible to payload', () => {
176
+ const r1 = actionsMap.TOGGLE_APP_VISIBLE(state, true)
177
+ expect(r1.appVisible).toBe(true)
178
+ const r2 = actionsMap.TOGGLE_APP_VISIBLE(state, false)
179
+ expect(r2.appVisible).toBe(false)
180
+ })
181
+
155
182
  test('TOGGLE_BUTTON_PRESSED adds/removes button', () => {
156
183
  const r1 = actionsMap.TOGGLE_BUTTON_PRESSED(state, { id: 'btn6', isPressed: true })
157
184
  expect(r1.pressedButtons.has('btn6')).toBe(true)
@@ -1,7 +1,11 @@
1
1
  // src/App/store/dispatchMiddleware.js
2
2
  import { EVENTS as events } from '../../config/events.js'
3
- import { defaultPanelConfig } from '../../config/appConfig.js'
3
+ import { defaultPanelConfig, defaultButtonConfig, defaultControlConfig } from '../../config/appConfig.js'
4
4
  import { deepMerge } from '../../utils/deepMerge.js'
5
+ import { allowedSlots } from '../renderer/slots.js'
6
+ import { logger } from '../../services/logger.js'
7
+
8
+ const BREAKPOINTS = ['mobile', 'tablet', 'desktop']
5
9
 
6
10
  /**
7
11
  * Determines which panels were implicitly closed when opening a new panel
@@ -81,9 +85,37 @@ export function handleActionSideEffects (action, previousState, panelConfig, eve
81
85
  })
82
86
  }
83
87
 
88
+ if (type === 'ADD_BUTTON') {
89
+ const { id, config } = payload
90
+ const mergedConfig = deepMerge(defaultButtonConfig, config)
91
+ BREAKPOINTS.forEach(bp => {
92
+ const slot = mergedConfig[bp]?.slot
93
+ if (slot && !allowedSlots.button.includes(slot)) {
94
+ logger.warn(`button "${id}" has invalid slot "${slot}" at breakpoint "${bp}". Allowed slots: ${allowedSlots.button.join(', ')}.`)
95
+ }
96
+ })
97
+ }
98
+
99
+ if (type === 'ADD_CONTROL') {
100
+ const { id, config } = payload
101
+ const mergedConfig = deepMerge(defaultControlConfig, config)
102
+ BREAKPOINTS.forEach(bp => {
103
+ const slot = mergedConfig[bp]?.slot
104
+ if (slot && !allowedSlots.control.includes(slot)) {
105
+ logger.warn(`control "${id}" has invalid slot "${slot}" at breakpoint "${bp}". Allowed slots: ${allowedSlots.control.join(', ')}.`)
106
+ }
107
+ })
108
+ }
109
+
84
110
  if (type === 'ADD_PANEL') {
85
111
  const { id, config } = payload
86
112
  const mergedConfig = deepMerge(defaultPanelConfig, config)
113
+ BREAKPOINTS.forEach(bp => {
114
+ const slot = mergedConfig[bp]?.slot
115
+ if (slot && !allowedSlots.panel.includes(slot) && !slot.endsWith('-button')) {
116
+ logger.warn(`panel "${id}" has invalid slot "${slot}" at breakpoint "${bp}". Allowed slots: ${allowedSlots.panel.join(', ')}.`)
117
+ }
118
+ })
87
119
  const bpConfig = mergedConfig[previousState.breakpoint]
88
120
  if (bpConfig?.open) {
89
121
  queueMicrotask(() => {