@defra/interactive-map 0.0.16-alpha → 0.0.18-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.
- package/assets/images/slot-map.svg +264 -0
- package/dist/css/index.css +1 -1
- package/dist/esm/im-core.js +1 -1
- package/dist/esm/im-shell.js +1 -1
- package/dist/umd/im-core.js +1 -1
- package/dist/umd/index.js +1 -1
- package/docs/api/context.md +53 -7
- package/docs/api/map-style-config.md +41 -2
- package/docs/api/marker-config.md +53 -11
- package/docs/api/slots.md +16 -15
- package/docs/api/symbol-config.md +160 -0
- package/docs/api/symbol-registry.md +115 -0
- package/docs/api.md +25 -22
- package/docs/getting-started.md +4 -1
- package/docs/plugins/datasets.md +657 -0
- package/docs/plugins/interact.md +68 -43
- package/docs/plugins/search.md +15 -3
- package/docs/plugins.md +1 -1
- package/package.json +2 -2
- package/plugins/beta/datasets/dist/css/index.css +103 -15
- package/plugins/beta/datasets/dist/esm/im-datasets-plugin.js +1 -1
- package/plugins/beta/datasets/dist/esm/index.js +1 -1
- package/plugins/beta/datasets/dist/umd/im-datasets-plugin.js +1 -1
- package/plugins/beta/datasets/dist/umd/index.js +1 -1
- package/plugins/beta/datasets/src/DatasetsInit.jsx +29 -9
- package/plugins/beta/datasets/src/adapters/maplibre/index.js +18 -0
- package/plugins/beta/datasets/src/adapters/maplibre/layerBuilders.js +159 -0
- package/plugins/beta/datasets/src/adapters/maplibre/layerIds.js +75 -0
- package/plugins/beta/datasets/src/adapters/maplibre/maplibreLayerAdapter.js +440 -0
- package/plugins/beta/datasets/src/adapters/maplibre/patternImages.js +27 -0
- package/plugins/beta/datasets/src/adapters/maplibre/symbolImages.js +31 -0
- package/plugins/beta/datasets/src/api/addDataset.js +2 -8
- package/plugins/beta/datasets/src/api/getOpacity.js +17 -0
- package/plugins/beta/datasets/src/api/getStyle.js +13 -0
- package/plugins/beta/datasets/src/api/removeDataset.js +2 -44
- package/plugins/beta/datasets/src/api/setData.js +10 -0
- package/plugins/beta/datasets/src/api/setDatasetVisibility.js +37 -0
- package/plugins/beta/datasets/src/api/setFeatureVisibility.js +22 -0
- package/plugins/beta/datasets/src/api/setOpacity.js +29 -0
- package/plugins/beta/datasets/src/api/setStyle.js +22 -0
- package/plugins/beta/datasets/src/components/EmptyKey.jsx +7 -0
- package/plugins/beta/datasets/src/components/EmptyKey.test.jsx +21 -0
- package/plugins/beta/datasets/src/components/KeySvg.jsx +24 -0
- package/plugins/beta/datasets/src/components/KeySvgLine.jsx +19 -0
- package/plugins/beta/datasets/src/components/KeySvgPattern.jsx +15 -0
- package/plugins/beta/datasets/src/components/KeySvgRect.jsx +22 -0
- package/plugins/beta/datasets/src/components/KeySvgSymbol.jsx +16 -0
- package/plugins/beta/datasets/src/components/svgProperties.js +20 -0
- package/plugins/beta/datasets/src/datasets.js +39 -56
- package/plugins/beta/datasets/src/defaults.js +44 -8
- package/plugins/beta/datasets/src/fetch/createDynamicSource.js +34 -25
- package/plugins/beta/datasets/src/fetch/fetchGeoJSON.js +2 -2
- package/plugins/beta/datasets/src/index.js +2 -1
- package/plugins/beta/datasets/src/manifest.js +25 -17
- package/plugins/beta/datasets/src/panels/Key.jsx +51 -51
- package/plugins/beta/datasets/src/panels/Key.module.scss +59 -9
- package/plugins/beta/datasets/src/panels/Layers.jsx +132 -29
- package/plugins/beta/datasets/src/panels/Layers.module.scss +56 -8
- package/plugins/beta/datasets/src/reducer.js +134 -9
- package/plugins/beta/datasets/src/reducers/keyReducer.js +34 -0
- package/plugins/beta/datasets/src/utils/bbox.js +7 -5
- package/plugins/beta/datasets/src/utils/filters.js +5 -2
- package/plugins/beta/datasets/src/utils/mergeSublayer.js +86 -0
- package/plugins/beta/draw-es/dist/esm/im-draw-es-plugin.js +1 -1
- package/plugins/beta/draw-es/src/DrawInit.jsx +3 -2
- package/plugins/beta/draw-ml/dist/css/index.css +21 -1
- package/plugins/beta/draw-ml/dist/esm/im-draw-ml-plugin.js +1 -1
- package/plugins/beta/draw-ml/dist/umd/im-draw-ml-plugin.js +1 -1
- package/plugins/beta/draw-ml/dist/umd/index.js +1 -1
- package/plugins/beta/draw-ml/src/DrawInit.jsx +4 -3
- package/plugins/beta/draw-ml/src/draw.scss +0 -7
- package/plugins/beta/draw-ml/src/manifest.js +16 -16
- package/plugins/beta/frame/dist/esm/im-frame-plugin.js +1 -1
- package/plugins/beta/frame/dist/umd/im-frame-plugin.js +1 -1
- package/plugins/beta/frame/src/Frame.jsx +5 -5
- package/plugins/beta/map-styles/dist/esm/im-map-styles-plugin.js +1 -1
- package/plugins/beta/map-styles/dist/umd/im-map-styles-plugin.js +1 -1
- package/plugins/beta/map-styles/dist/umd/index.js +1 -1
- package/plugins/beta/map-styles/src/MapStyles.jsx +5 -4
- package/plugins/beta/map-styles/src/MapStylesInit.jsx +5 -4
- package/plugins/beta/map-styles/src/manifest.js +1 -1
- package/plugins/beta/scale-bar/dist/css/index.css +1 -1
- package/plugins/beta/scale-bar/dist/esm/im-scale-bar-plugin.js +1 -1
- package/plugins/beta/scale-bar/dist/umd/im-scale-bar-plugin.js +1 -1
- package/plugins/beta/scale-bar/src/index.test.js +3 -3
- package/plugins/beta/scale-bar/src/manifest.js +3 -3
- package/plugins/beta/scale-bar/src/scaleBar.scss +2 -1
- package/plugins/interact/dist/css/index.css +1 -1
- package/plugins/interact/dist/esm/im-interact-plugin.js +1 -1
- package/plugins/interact/dist/umd/im-interact-plugin.js +1 -1
- package/plugins/interact/dist/umd/index.js +1 -1
- package/plugins/interact/src/InteractInit.jsx +14 -5
- package/plugins/interact/src/InteractInit.test.js +26 -6
- package/plugins/interact/src/api/enable.test.js +7 -7
- package/plugins/interact/src/defaults.js +4 -6
- package/plugins/interact/src/events.js +9 -6
- package/plugins/interact/src/events.test.js +28 -4
- package/plugins/interact/src/hooks/useHighlightSync.js +3 -3
- package/plugins/interact/src/hooks/useHighlightSync.test.js +6 -6
- package/plugins/interact/src/hooks/useHoverCursor.js +10 -0
- package/plugins/interact/src/hooks/useHoverCursor.test.js +44 -0
- package/plugins/interact/src/hooks/useInteractionHandlers.js +111 -69
- package/plugins/interact/src/hooks/useInteractionHandlers.test.js +147 -32
- package/plugins/interact/src/interact.scss +0 -7
- package/plugins/interact/src/manifest.js +14 -18
- package/plugins/interact/src/manifest.test.js +3 -1
- package/plugins/interact/src/reducer.js +23 -4
- package/plugins/interact/src/reducer.test.js +60 -11
- package/plugins/interact/src/utils/buildStylesMap.js +17 -4
- package/plugins/interact/src/utils/buildStylesMap.test.js +16 -2
- package/plugins/interact/src/utils/featureQueries.js +11 -6
- package/plugins/interact/src/utils/featureQueries.test.js +8 -1
- package/plugins/search/dist/css/index.css +1 -1
- package/plugins/search/dist/esm/im-search-plugin.js +1 -1
- package/plugins/search/dist/umd/im-search-plugin.js +1 -1
- package/plugins/search/src/Search.jsx +3 -1
- package/plugins/search/src/components/Form/Form.module.scss +2 -1
- package/plugins/search/src/events/fetchSuggestions.js +6 -4
- package/plugins/search/src/events/fetchSuggestions.test.js +26 -4
- package/plugins/search/src/events/formHandlers.js +3 -3
- package/plugins/search/src/events/formHandlers.test.js +1 -1
- package/plugins/search/src/events/suggestionHandlers.js +2 -2
- package/plugins/search/src/events/suggestionHandlers.test.js +1 -1
- package/plugins/search/src/utils/updateMap.js +3 -3
- package/plugins/search/src/utils/updateMap.test.js +3 -3
- package/providers/maplibre/dist/esm/im-maplibre-provider.js +1 -1
- package/providers/maplibre/dist/umd/im-maplibre-framework.js +1 -1
- package/providers/maplibre/dist/umd/im-maplibre-framework.js.LICENSE.txt +1 -1
- package/providers/maplibre/dist/umd/im-maplibre-provider.js +1 -1
- package/providers/maplibre/dist/umd/index.js +1 -1
- package/providers/maplibre/src/appEvents.js +7 -0
- package/providers/maplibre/src/appEvents.test.js +18 -4
- package/providers/maplibre/src/maplibreProvider.js +52 -0
- package/providers/maplibre/src/maplibreProvider.test.js +105 -1
- package/providers/maplibre/src/utils/highlightFeatures.js +37 -7
- package/providers/maplibre/src/utils/highlightFeatures.test.js +153 -95
- package/providers/maplibre/src/utils/hoverCursor.js +61 -0
- package/providers/maplibre/src/utils/hoverCursor.test.js +130 -0
- package/providers/maplibre/src/utils/patternImages.js +70 -0
- package/providers/maplibre/src/utils/patternImages.test.js +180 -0
- package/providers/maplibre/src/utils/queryFeatures.js +38 -16
- package/providers/maplibre/src/utils/queryFeatures.test.js +20 -3
- package/providers/maplibre/src/utils/rasteriseToImageData.js +30 -0
- package/providers/maplibre/src/utils/rasteriseToImageData.test.js +69 -0
- package/providers/maplibre/src/utils/symbolImages.js +147 -0
- package/providers/maplibre/src/utils/symbolImages.test.js +248 -0
- package/src/App/components/Actions/Actions.jsx +2 -2
- package/src/App/components/Actions/Actions.module.scss +0 -7
- package/src/App/components/Actions/Actions.test.jsx +1 -1
- package/src/App/components/Icon/Icon.jsx +3 -2
- package/src/App/components/Icon/Icon.module.scss +4 -0
- package/src/App/components/Icon/Icon.test.jsx +43 -4
- package/src/App/components/MapButton/MapButton.jsx +42 -17
- package/src/App/components/MapButton/MapButton.module.scss +4 -13
- package/src/App/components/MapButton/MapButton.test.jsx +27 -3
- package/src/App/components/Markers/Markers.jsx +122 -27
- package/src/App/components/Markers/Markers.module.scss +0 -10
- package/src/App/components/Markers/Markers.test.jsx +246 -0
- package/src/App/components/PopupMenu/PopupMenu.jsx +51 -274
- package/src/App/components/PopupMenu/PopupMenu.module.scss +14 -7
- package/src/App/components/PopupMenu/PopupMenu.test.jsx +70 -1
- package/src/App/components/PopupMenu/usePopupMenu.js +258 -0
- package/src/App/hooks/useButtonStateEvaluator.js +12 -2
- package/src/App/hooks/useButtonStateEvaluator.test.js +38 -4
- package/src/App/hooks/useInterfaceAPI.js +6 -0
- package/src/App/hooks/useInterfaceAPI.test.js +156 -0
- package/src/App/hooks/useLayoutMeasurements.js +84 -18
- package/src/App/hooks/useLayoutMeasurements.test.js +124 -17
- package/src/App/hooks/useMarkersAPI.js +2 -5
- package/src/App/hooks/useMarkersAPI.test.js +4 -4
- package/src/App/layout/Layout.jsx +14 -9
- package/src/App/layout/Layout.test.jsx +6 -4
- package/src/App/layout/layout.module.scss +67 -29
- package/src/App/registry/pluginRegistry.js +1 -1
- package/src/App/renderer/HtmlElementHost.jsx +2 -1
- package/src/App/renderer/HtmlElementHost.test.jsx +7 -7
- package/src/App/renderer/mapButtons.js +1 -1
- package/src/App/renderer/mapPanels.test.js +2 -2
- package/src/App/renderer/slotHelpers.js +2 -2
- package/src/App/renderer/slotHelpers.test.js +5 -5
- package/src/App/renderer/slots.js +9 -5
- package/src/App/store/AppProvider.jsx +3 -1
- package/src/App/store/AppProvider.test.jsx +1 -1
- package/src/App/store/ServiceProvider.jsx +8 -4
- package/src/App/store/appActionsMap.js +16 -0
- package/src/App/store/appActionsMap.test.js +27 -0
- package/src/App/store/appDispatchMiddleware.js +1 -1
- package/src/App/store/appDispatchMiddleware.test.js +2 -2
- package/src/App/store/appReducer.js +2 -0
- package/src/App/store/mapActionsMap.js +4 -6
- package/src/App/store/mapActionsMap.test.js +3 -2
- package/src/App/store/mapReducer.js +2 -1
- package/src/InteractiveMap/InteractiveMap.js +4 -0
- package/src/config/appConfig.js +5 -8
- package/src/config/appConfig.test.js +1 -2
- package/src/config/defaults.js +0 -2
- package/src/config/events.js +28 -0
- package/src/config/mapTheme.js +56 -0
- package/src/config/patternConfig.js +16 -0
- package/src/config/symbolConfig.js +80 -0
- package/src/scss/main.scss +1 -0
- package/src/scss/settings/_colors.scss +0 -9
- package/src/scss/settings/_dimensions.scss +0 -1
- package/src/services/patternRegistry.js +40 -0
- package/src/services/patternRegistry.test.js +48 -0
- package/src/services/symbolRegistry.js +113 -0
- package/src/services/symbolRegistry.test.js +262 -0
- package/src/types.js +93 -11
- package/src/utils/getSafeZoneInset.js +9 -7
- package/src/utils/getSafeZoneInset.test.js +10 -10
- package/src/utils/patternUtils.js +94 -0
- package/src/utils/patternUtils.test.js +160 -0
- package/src/utils/symbolUtils.js +85 -0
- package/src/utils/symbolUtils.test.js +156 -0
- package/webpack.dev.mjs +1 -1
- package/docs/api/slot-map.svg +0 -1
- package/plugins/beta/datasets/src/api/hideDataset.js +0 -14
- package/plugins/beta/datasets/src/api/hideFeatures.js +0 -41
- package/plugins/beta/datasets/src/api/showDataset.js +0 -14
- package/plugins/beta/datasets/src/api/showFeatures.js +0 -44
- package/plugins/beta/datasets/src/handleSetMapStyle.js +0 -54
- package/plugins/beta/datasets/src/mapLayers.js +0 -164
- /package/src/{utils → services}/logger.js +0 -0
- /package/src/{utils → services}/logger.test.js +0 -0
|
@@ -12,8 +12,47 @@ const topColWidth = (left, right) =>
|
|
|
12
12
|
const subSlotMaxHeight = (columnHeight, siblingButtons, gap) =>
|
|
13
13
|
columnHeight - (siblingButtons ? siblingButtons + gap : 0)
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Manages all layout measurements for the map overlay and dispatches the safe
|
|
17
|
+
* zone inset used by the map to pad `fitBounds` / `setView` operations.
|
|
18
|
+
*
|
|
19
|
+
* ## Lifecycle
|
|
20
|
+
*
|
|
21
|
+
* The safe zone must only be dispatched once every plugin button's reactive
|
|
22
|
+
* props (`hiddenWhen`, `enableWhen`, `pressedWhen`, `expandedWhen`) have been
|
|
23
|
+
* evaluated for the current app/map state. Dispatching too early — before
|
|
24
|
+
* buttons that affect layout (e.g. the actions bar) have their correct
|
|
25
|
+
* visibility — produces a stale inset that causes the map to jump when the UI
|
|
26
|
+
* then settles into its real state.
|
|
27
|
+
*
|
|
28
|
+
* ### Trigger events
|
|
29
|
+
* The following state changes can alter which buttons are visible and therefore
|
|
30
|
+
* how much space the UI occupies:
|
|
31
|
+
* - `breakpoint` — responsive layout changes (desktop ↔ mobile / tablet)
|
|
32
|
+
* - `mapSize` — map container size variant changes
|
|
33
|
+
* - `isMapReady` — plugins are enabled on `map:ready`, changing button visibility
|
|
34
|
+
* - `isFullscreen` — fullscreen entry/exit changes which buttons are visible
|
|
35
|
+
* - `appVisible` — app shown/hidden by parent HTML outside React (hybrid mode)
|
|
36
|
+
*
|
|
37
|
+
* When any of these change, `CLEAR_PLUGINS_EVALUATED` is dispatched (Effect 2),
|
|
38
|
+
* which prevents the safe zone from being re-dispatched until
|
|
39
|
+
* `useButtonStateEvaluator` has completed a full pass with no button state
|
|
40
|
+
* changes and sets `PLUGINS_EVALUATED` again.
|
|
41
|
+
*
|
|
42
|
+
* ### Safe zone dispatch
|
|
43
|
+
* Effect 3 fires whenever `arePluginsEvaluated` transitions to `true`, at which
|
|
44
|
+
* point DOM dimensions are stable and `getSafeZoneInset` can be read reliably.
|
|
45
|
+
* A `requestAnimationFrame` is used to ensure the browser has committed all
|
|
46
|
+
* layout changes before measuring.
|
|
47
|
+
*
|
|
48
|
+
* ### Resize observer
|
|
49
|
+
* Effect 4 keeps CSS custom properties up to date whenever any observed element
|
|
50
|
+
* resizes (e.g. panels opening, banner appearing, actions buttons toggling).
|
|
51
|
+
* It does not dispatch the safe zone — safe zone dispatch is owned entirely by
|
|
52
|
+
* Effect 3 to prevent jumps on panel open/close and other non-structural resizes.
|
|
53
|
+
*/
|
|
15
54
|
export function useLayoutMeasurements () {
|
|
16
|
-
const { dispatch, breakpoint, layoutRefs } = useApp()
|
|
55
|
+
const { dispatch, breakpoint, layoutRefs, arePluginsEvaluated, appVisible, isFullscreen } = useApp()
|
|
17
56
|
const { mapSize, isMapReady } = useMap()
|
|
18
57
|
|
|
19
58
|
const {
|
|
@@ -23,24 +62,28 @@ export function useLayoutMeasurements () {
|
|
|
23
62
|
topRef,
|
|
24
63
|
topLeftColRef,
|
|
25
64
|
topRightColRef,
|
|
26
|
-
footerRef,
|
|
27
|
-
actionsRef,
|
|
28
65
|
leftTopRef,
|
|
29
66
|
leftBottomRef,
|
|
30
67
|
rightTopRef,
|
|
31
|
-
rightBottomRef
|
|
68
|
+
rightBottomRef,
|
|
69
|
+
bottomRef,
|
|
70
|
+
bottomRightRef,
|
|
71
|
+
attributionsRef,
|
|
72
|
+
drawerRef,
|
|
73
|
+
actionsRef
|
|
32
74
|
} = layoutRefs
|
|
33
75
|
|
|
34
|
-
//
|
|
35
|
-
// 1. Calculate layout CSS vars (side effect)
|
|
36
|
-
//
|
|
76
|
+
// --------------------------------
|
|
77
|
+
// 1. Calculate layout CSS vars (pure side effect, no dispatch)
|
|
78
|
+
// --------------------------------
|
|
37
79
|
const calculateLayout = () => {
|
|
38
80
|
const appContainer = appContainerRef.current
|
|
39
81
|
const main = mainRef.current
|
|
40
82
|
const top = topRef.current
|
|
41
83
|
const topLeftCol = topLeftColRef.current
|
|
42
84
|
const topRightCol = topRightColRef.current
|
|
43
|
-
const bottom =
|
|
85
|
+
const bottom = bottomRef.current
|
|
86
|
+
const attributions = attributionsRef.current
|
|
44
87
|
|
|
45
88
|
if ([main, top, bottom].some(r => !r)) {
|
|
46
89
|
return
|
|
@@ -60,10 +103,17 @@ export function useLayoutMeasurements () {
|
|
|
60
103
|
appContainer.style.setProperty('--left-top-max-height', `${leftColumnHeight}px`)
|
|
61
104
|
|
|
62
105
|
// === Right container offsets ===
|
|
106
|
+
// Mirrors the top formula (topRightCol.offsetHeight + top.offsetTop):
|
|
107
|
+
// bottomRight.offsetHeight is 0 when no buttons so the offset collapses to just
|
|
108
|
+
// the padding between the bottom of the bottom container and the bottom of main.
|
|
109
|
+
const bottomRightHeight = bottomRightRef?.current?.offsetHeight ?? 0
|
|
110
|
+
const bottomContainerPad = main.offsetHeight - bottom.offsetTop - bottom.offsetHeight
|
|
63
111
|
const rightOffsetTop = topRightCol.offsetHeight + top.offsetTop
|
|
64
|
-
const
|
|
112
|
+
const rightEffectiveBottom = bottom.offsetTop + bottom.offsetHeight - bottomRightHeight
|
|
113
|
+
const rightColumnHeight = rightEffectiveBottom - rightOffsetTop - dividerGap
|
|
114
|
+
const rightOffsetBottom = bottomContainerPad + (bottomRightHeight > 0 ? (bottomRightHeight + dividerGap) : attributions.offsetHeight)
|
|
65
115
|
appContainer.style.setProperty('--right-offset-top', `${rightOffsetTop}px`)
|
|
66
|
-
appContainer.style.setProperty('--right-offset-bottom', `${
|
|
116
|
+
appContainer.style.setProperty('--right-offset-bottom', `${rightOffsetBottom}px`)
|
|
67
117
|
appContainer.style.setProperty('--right-top-max-height', `${rightColumnHeight}px`)
|
|
68
118
|
|
|
69
119
|
// === Sub-slot panel max-heights ===
|
|
@@ -74,22 +124,38 @@ export function useLayoutMeasurements () {
|
|
|
74
124
|
}
|
|
75
125
|
|
|
76
126
|
// --------------------------------
|
|
77
|
-
// 2.
|
|
127
|
+
// 2. Clear the evaluated flag when structural inputs change so the safe zone
|
|
128
|
+
// is not dispatched until useButtonStateEvaluator has completed a full
|
|
129
|
+
// pass with the new app/map state and set PLUGINS_EVALUATED.
|
|
78
130
|
// --------------------------------
|
|
79
131
|
useLayoutEffect(() => {
|
|
80
|
-
|
|
81
|
-
|
|
132
|
+
dispatch({ type: 'CLEAR_PLUGINS_EVALUATED' })
|
|
133
|
+
}, [breakpoint, mapSize, isMapReady, appVisible, isFullscreen])
|
|
82
134
|
|
|
83
|
-
|
|
135
|
+
// --------------------------------
|
|
136
|
+
// 3. Once all plugin button props have been evaluated (arePluginsEvaluated),
|
|
137
|
+
// recalculate layout and dispatch the safe zone inset.
|
|
138
|
+
// RAF required to ensure browser layout is committed before measuring.
|
|
139
|
+
// --------------------------------
|
|
140
|
+
useLayoutEffect(() => {
|
|
141
|
+
if (!arePluginsEvaluated) {
|
|
142
|
+
return
|
|
143
|
+
}
|
|
144
|
+
requestAnimationFrame(() => {
|
|
145
|
+
calculateLayout()
|
|
84
146
|
const safeZoneInset = getSafeZoneInset(layoutRefs)
|
|
85
|
-
|
|
147
|
+
if (safeZoneInset) {
|
|
148
|
+
dispatch({ type: 'SET_SAFE_ZONE_INSET', payload: { safeZoneInset } })
|
|
149
|
+
}
|
|
86
150
|
})
|
|
87
|
-
}, [
|
|
151
|
+
}, [arePluginsEvaluated])
|
|
88
152
|
|
|
89
153
|
// --------------------------------
|
|
90
|
-
//
|
|
154
|
+
// 4. Recalculate CSS vars whenever observed elements resize (panels, banner,
|
|
155
|
+
// actions buttons, etc.). Safe zone is intentionally not dispatched here —
|
|
156
|
+
// that is Effect 3's responsibility.
|
|
91
157
|
// --------------------------------
|
|
92
|
-
useResizeObserver([bannerRef, mainRef, topRef, topLeftColRef, topRightColRef, actionsRef,
|
|
158
|
+
useResizeObserver([bannerRef, mainRef, topRef, topLeftColRef, topRightColRef, actionsRef, bottomRef, bottomRightRef, leftTopRef, leftBottomRef, rightTopRef, rightBottomRef, drawerRef], () => {
|
|
93
159
|
requestAnimationFrame(() => {
|
|
94
160
|
calculateLayout()
|
|
95
161
|
})
|
|
@@ -24,18 +24,21 @@ const refs = (o = {}) => ({
|
|
|
24
24
|
topRef: { current: o.top === null ? null : el({ offsetTop: 10, ...o.top }) },
|
|
25
25
|
topLeftColRef: { current: el({ offsetHeight: 50, offsetWidth: 200, ...o.topLeftCol }) },
|
|
26
26
|
topRightColRef: { current: el({ offsetHeight: 40, offsetWidth: 180, ...o.topRightCol }) },
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
bottomRef: { current: o.bottom === null ? null : el({ offsetTop: 400, ...o.bottom }) },
|
|
28
|
+
bottomRightRef: { current: el({ offsetTop: 400, ...o.bottomRight }) },
|
|
29
29
|
leftTopRef: { current: el({ offsetHeight: 0, ...o.leftTop }) },
|
|
30
30
|
leftBottomRef: { current: el({ offsetHeight: 0, ...o.leftBottom }) },
|
|
31
31
|
rightTopRef: { current: el({ offsetHeight: 0, ...o.rightTop }) },
|
|
32
|
-
rightBottomRef: { current: el({ offsetHeight: 0, ...o.rightBottom }) }
|
|
32
|
+
rightBottomRef: { current: el({ offsetHeight: 0, ...o.rightBottom }) },
|
|
33
|
+
attributionsRef: { current: el({ offsetHeight: 16, ...o.attributions }) },
|
|
34
|
+
drawerRef: { current: el(o.drawer) },
|
|
35
|
+
actionsRef: { current: el({ offsetTop: 450, ...o.actions }) }
|
|
33
36
|
})
|
|
34
37
|
|
|
35
38
|
const setup = (o = {}) => {
|
|
36
39
|
const dispatch = jest.fn()
|
|
37
40
|
const layoutRefs = refs(o.refs)
|
|
38
|
-
useApp.mockReturnValue({ dispatch, breakpoint: 'desktop', layoutRefs, ...o.app })
|
|
41
|
+
useApp.mockReturnValue({ dispatch, breakpoint: 'desktop', layoutRefs, arePluginsEvaluated: true, ...o.app })
|
|
39
42
|
useMap.mockReturnValue({ mapSize: { width: 800, height: 600 }, isMapReady: true, ...o.map })
|
|
40
43
|
getSafeZoneInset.mockReturnValue({ top: 0, right: 0, bottom: 0, left: 0 })
|
|
41
44
|
return { dispatch, layoutRefs }
|
|
@@ -56,7 +59,7 @@ describe('useLayoutMeasurements', () => {
|
|
|
56
59
|
})
|
|
57
60
|
|
|
58
61
|
test('early return when required refs are null', () => {
|
|
59
|
-
const { layoutRefs } = setup({ refs: { main: null, top: null,
|
|
62
|
+
const { layoutRefs } = setup({ refs: { main: null, top: null, bottom: null } })
|
|
60
63
|
renderHook(() => useLayoutMeasurements())
|
|
61
64
|
expect(layoutRefs.appContainerRef.current.style.setProperty).not.toHaveBeenCalled()
|
|
62
65
|
})
|
|
@@ -71,7 +74,7 @@ describe('useLayoutMeasurements', () => {
|
|
|
71
74
|
|
|
72
75
|
test.each([
|
|
73
76
|
['right-offset-top', { topRightCol: { offsetHeight: 80 }, top: { offsetTop: 15 } }, '95px'],
|
|
74
|
-
['right-offset-bottom', { main: { offsetHeight: 600 },
|
|
77
|
+
['right-offset-bottom', { main: { offsetHeight: 600 }, bottom: { offsetTop: 500 } }, '116px'],
|
|
75
78
|
// leftColumnHeight = 400 - (50+10) - 8 = 332; rightColumnHeight = 400 - (40+10) - 8 = 342
|
|
76
79
|
['left-top-max-height', {}, '332px'],
|
|
77
80
|
['right-top-max-height', {}, '342px']
|
|
@@ -107,6 +110,26 @@ describe('useLayoutMeasurements', () => {
|
|
|
107
110
|
expect(layoutRefs.appContainerRef.current.style.setProperty).toHaveBeenCalledWith('--top-col-width', expected)
|
|
108
111
|
})
|
|
109
112
|
|
|
113
|
+
test('uses 0 when bottomRightRef current is null', () => {
|
|
114
|
+
const { layoutRefs } = setup()
|
|
115
|
+
layoutRefs.bottomRightRef.current = null
|
|
116
|
+
renderHook(() => useLayoutMeasurements())
|
|
117
|
+
expect(layoutRefs.appContainerRef.current.style.setProperty).toHaveBeenCalledWith('--right-offset-bottom', '116px')
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
test('uses bottomRight height when bottomRightHeight > 0', () => {
|
|
121
|
+
const { layoutRefs } = setup({
|
|
122
|
+
refs: {
|
|
123
|
+
bottomRight: { offsetHeight: 20 } // 👈 triggers TRUE branch
|
|
124
|
+
}
|
|
125
|
+
})
|
|
126
|
+
renderHook(() => useLayoutMeasurements())
|
|
127
|
+
// bottomContainerPad = 500 - 400 - 0 = 100
|
|
128
|
+
// expected = 100 + (20 + 8) = 128
|
|
129
|
+
expect(layoutRefs.appContainerRef.current.style.setProperty)
|
|
130
|
+
.toHaveBeenCalledWith('--right-offset-bottom', '128px')
|
|
131
|
+
})
|
|
132
|
+
|
|
110
133
|
test('uses 0 when sub-slot refs have null current', () => {
|
|
111
134
|
const { layoutRefs } = setup()
|
|
112
135
|
layoutRefs.leftTopRef.current = null
|
|
@@ -119,31 +142,100 @@ describe('useLayoutMeasurements', () => {
|
|
|
119
142
|
expect(layoutRefs.appContainerRef.current.style.setProperty).toHaveBeenCalledWith('--right-bottom-panel-max-height', '342px')
|
|
120
143
|
})
|
|
121
144
|
|
|
122
|
-
test('dispatches safe zone inset', () => {
|
|
123
|
-
const { dispatch, layoutRefs } = setup()
|
|
145
|
+
test('dispatches safe zone inset on desktop (post-batch RAF read only)', () => {
|
|
146
|
+
const { dispatch, layoutRefs } = setup({ app: { breakpoint: 'desktop' } })
|
|
124
147
|
getSafeZoneInset.mockReturnValue({ top: 10, right: 5, bottom: 15, left: 5 })
|
|
125
148
|
renderHook(() => useLayoutMeasurements())
|
|
126
149
|
expect(getSafeZoneInset).toHaveBeenCalledWith(layoutRefs)
|
|
127
150
|
expect(dispatch).toHaveBeenCalledWith({ type: 'SET_SAFE_ZONE_INSET', payload: { safeZoneInset: { top: 10, right: 5, bottom: 15, left: 5 } } })
|
|
128
151
|
})
|
|
129
152
|
|
|
130
|
-
test('
|
|
153
|
+
test('dispatches safe zone inset on mobile', () => {
|
|
154
|
+
const { dispatch } = setup({ app: { breakpoint: 'mobile' } })
|
|
155
|
+
getSafeZoneInset.mockReturnValue({ top: 10, right: 5, bottom: 40, left: 5 })
|
|
156
|
+
renderHook(() => useLayoutMeasurements())
|
|
157
|
+
expect(dispatch).toHaveBeenCalledWith({
|
|
158
|
+
type: 'SET_SAFE_ZONE_INSET',
|
|
159
|
+
payload: { safeZoneInset: { top: 10, right: 5, bottom: 40, left: 5 } }
|
|
160
|
+
})
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
test('does not dispatch SET_SAFE_ZONE_INSET when getSafeZoneInset returns undefined', () => {
|
|
164
|
+
const { dispatch } = setup()
|
|
165
|
+
getSafeZoneInset.mockReturnValue(undefined)
|
|
166
|
+
renderHook(() => useLayoutMeasurements())
|
|
167
|
+
expect(dispatch).not.toHaveBeenCalledWith(expect.objectContaining({ type: 'SET_SAFE_ZONE_INSET' }))
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
test('does not dispatch safe zone when arePluginsEvaluated is false', () => {
|
|
171
|
+
const { dispatch } = setup({ app: { arePluginsEvaluated: false } })
|
|
172
|
+
renderHook(() => useLayoutMeasurements())
|
|
173
|
+
expect(dispatch).not.toHaveBeenCalledWith(expect.objectContaining({ type: 'SET_SAFE_ZONE_INSET' }))
|
|
174
|
+
expect(layoutRefs => layoutRefs).toBeDefined() // no layout calculation
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
test('re-dispatches safe zone when arePluginsEvaluated becomes true', () => {
|
|
178
|
+
setup({ app: { arePluginsEvaluated: false } })
|
|
179
|
+
const { rerender } = renderHook(() => useLayoutMeasurements())
|
|
180
|
+
const { dispatch } = setup({ app: { arePluginsEvaluated: true } })
|
|
181
|
+
getSafeZoneInset.mockReturnValue({ top: 5, right: 5, bottom: 60, left: 5 })
|
|
182
|
+
rerender()
|
|
183
|
+
expect(dispatch).toHaveBeenCalledWith({
|
|
184
|
+
type: 'SET_SAFE_ZONE_INSET',
|
|
185
|
+
payload: { safeZoneInset: { top: 5, right: 5, bottom: 60, left: 5 } }
|
|
186
|
+
})
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
test('dispatches CLEAR_PLUGINS_EVALUATED when breakpoint changes', () => {
|
|
190
|
+
setup()
|
|
191
|
+
const { rerender } = renderHook(() => useLayoutMeasurements())
|
|
192
|
+
const { dispatch } = setup({ app: { breakpoint: 'mobile' } })
|
|
193
|
+
dispatch.mockClear()
|
|
194
|
+
rerender()
|
|
195
|
+
expect(dispatch).toHaveBeenCalledWith({ type: 'CLEAR_PLUGINS_EVALUATED' })
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
test('dispatches CLEAR_PLUGINS_EVALUATED when isMapReady changes', () => {
|
|
131
199
|
setup()
|
|
132
200
|
const { rerender } = renderHook(() => useLayoutMeasurements())
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
201
|
+
const { dispatch } = setup({ map: { isMapReady: false } })
|
|
202
|
+
dispatch.mockClear()
|
|
203
|
+
rerender()
|
|
204
|
+
expect(dispatch).toHaveBeenCalledWith({ type: 'CLEAR_PLUGINS_EVALUATED' })
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
test('dispatches CLEAR_PLUGINS_EVALUATED when isFullscreen changes', () => {
|
|
208
|
+
setup({ app: { isFullscreen: false } })
|
|
209
|
+
const { rerender } = renderHook(() => useLayoutMeasurements())
|
|
210
|
+
const { dispatch } = setup({ app: { isFullscreen: true } })
|
|
211
|
+
dispatch.mockClear()
|
|
212
|
+
rerender()
|
|
213
|
+
expect(dispatch).toHaveBeenCalledWith({ type: 'CLEAR_PLUGINS_EVALUATED' })
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
test('dispatches CLEAR_PLUGINS_EVALUATED when appVisible changes', () => {
|
|
217
|
+
setup({ app: { appVisible: false } })
|
|
218
|
+
const { rerender } = renderHook(() => useLayoutMeasurements())
|
|
219
|
+
const { dispatch } = setup({ app: { appVisible: true } })
|
|
220
|
+
dispatch.mockClear()
|
|
221
|
+
rerender()
|
|
222
|
+
expect(dispatch).toHaveBeenCalledWith({ type: 'CLEAR_PLUGINS_EVALUATED' })
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
test('recalculates layout when arePluginsEvaluated becomes true', () => {
|
|
226
|
+
setup({ app: { arePluginsEvaluated: false } })
|
|
227
|
+
const { rerender } = renderHook(() => useLayoutMeasurements())
|
|
228
|
+
const { layoutRefs } = setup({ app: { arePluginsEvaluated: true } })
|
|
229
|
+
layoutRefs.appContainerRef.current.style.setProperty.mockClear()
|
|
230
|
+
rerender()
|
|
231
|
+
expect(layoutRefs.appContainerRef.current.style.setProperty).toHaveBeenCalled()
|
|
140
232
|
})
|
|
141
233
|
|
|
142
234
|
test('sets up resize observer', () => {
|
|
143
235
|
const { layoutRefs } = setup()
|
|
144
236
|
renderHook(() => useLayoutMeasurements())
|
|
145
237
|
expect(useResizeObserver).toHaveBeenCalledWith(
|
|
146
|
-
[layoutRefs.bannerRef, layoutRefs.mainRef, layoutRefs.topRef, layoutRefs.topLeftColRef, layoutRefs.topRightColRef, layoutRefs.actionsRef, layoutRefs.
|
|
238
|
+
[layoutRefs.bannerRef, layoutRefs.mainRef, layoutRefs.topRef, layoutRefs.topLeftColRef, layoutRefs.topRightColRef, layoutRefs.actionsRef, layoutRefs.bottomRef, layoutRefs.bottomRightRef, layoutRefs.leftTopRef, layoutRefs.leftBottomRef, layoutRefs.rightTopRef, layoutRefs.rightBottomRef, layoutRefs.drawerRef],
|
|
147
239
|
expect.any(Function)
|
|
148
240
|
)
|
|
149
241
|
layoutRefs.appContainerRef.current.style.setProperty.mockClear()
|
|
@@ -151,4 +243,19 @@ describe('useLayoutMeasurements', () => {
|
|
|
151
243
|
expect(rafSpy).toHaveBeenCalled()
|
|
152
244
|
expect(layoutRefs.appContainerRef.current.style.setProperty).toHaveBeenCalled()
|
|
153
245
|
})
|
|
246
|
+
|
|
247
|
+
test('resize observer does not dispatch safe zone (safe zone is Effect 3 only)', () => {
|
|
248
|
+
const { dispatch } = setup()
|
|
249
|
+
renderHook(() => useLayoutMeasurements())
|
|
250
|
+
dispatch.mockClear()
|
|
251
|
+
useResizeObserver.mock.calls[0][1]()
|
|
252
|
+
expect(dispatch).not.toHaveBeenCalledWith(expect.objectContaining({ type: 'SET_SAFE_ZONE_INSET' }))
|
|
253
|
+
})
|
|
254
|
+
|
|
255
|
+
test('resize observer handles null mainRef without throwing', () => {
|
|
256
|
+
const { layoutRefs } = setup()
|
|
257
|
+
renderHook(() => useLayoutMeasurements())
|
|
258
|
+
layoutRefs.mainRef.current = null
|
|
259
|
+
expect(() => useResizeObserver.mock.calls[0][1]()).not.toThrow()
|
|
260
|
+
})
|
|
154
261
|
})
|
|
@@ -5,12 +5,9 @@ import { useService } from '../store/serviceContext.js'
|
|
|
5
5
|
import { scaleFactor } from '../../config/appConfig.js'
|
|
6
6
|
import { EVENTS as events } from '../../config/events.js'
|
|
7
7
|
|
|
8
|
-
// Vertical offset to align the marker tip with the coordinate point
|
|
9
|
-
const MARKER_ANCHOR_OFFSET_Y = 19
|
|
10
|
-
|
|
11
8
|
/**
|
|
12
9
|
* Projects geographic coordinates to screen pixel position, scaled for the
|
|
13
|
-
* current map size
|
|
10
|
+
* current map size. Anchor alignment is handled in CSS by the Markers component.
|
|
14
11
|
*
|
|
15
12
|
* @param {Array<number>} coords - [lng, lat] geographic coordinates
|
|
16
13
|
* @param {Object} mapProvider - Map provider instance with `mapToScreen` method
|
|
@@ -25,7 +22,7 @@ export const projectCoords = (coords, mapProvider, mapSize, isMapReady) => {
|
|
|
25
22
|
const { x, y } = mapProvider.mapToScreen(coords)
|
|
26
23
|
return {
|
|
27
24
|
x: x * scaleFactor[mapSize],
|
|
28
|
-
y: y * scaleFactor[mapSize]
|
|
25
|
+
y: y * scaleFactor[mapSize]
|
|
29
26
|
}
|
|
30
27
|
}
|
|
31
28
|
|
|
@@ -19,7 +19,7 @@ describe('projectCoords', () => {
|
|
|
19
19
|
const mockProvider = { mapToScreen: jest.fn(() => ({ x: 100, y: 200 })) }
|
|
20
20
|
|
|
21
21
|
it('returns scaled coordinates when ready', () => {
|
|
22
|
-
expect(projectCoords({ lat: 1, lng: 1 }, mockProvider, 'medium', true)).toEqual({ x: 200, y:
|
|
22
|
+
expect(projectCoords({ lat: 1, lng: 1 }, mockProvider, 'medium', true)).toEqual({ x: 200, y: 400 })
|
|
23
23
|
})
|
|
24
24
|
|
|
25
25
|
it('returns zero when not ready or no provider', () => {
|
|
@@ -102,7 +102,7 @@ describe('useMarkers', () => {
|
|
|
102
102
|
|
|
103
103
|
const renderCallback = mockEventBus.on.mock.calls.find(call => call[0] === 'map:render')[1]
|
|
104
104
|
act(() => renderCallback())
|
|
105
|
-
expect(mockElement.style.transform).toBe('translate(200px,
|
|
105
|
+
expect(mockElement.style.transform).toBe('translate(200px, 400px)')
|
|
106
106
|
})
|
|
107
107
|
|
|
108
108
|
it('skips map:render when not ready or no provider (line 60)', () => {
|
|
@@ -126,7 +126,7 @@ describe('useMarkers', () => {
|
|
|
126
126
|
isMapReady: true
|
|
127
127
|
})
|
|
128
128
|
rerender()
|
|
129
|
-
expect(mockElement.style.transform).toBe('translate(300px,
|
|
129
|
+
expect(mockElement.style.transform).toBe('translate(300px, 600px)')
|
|
130
130
|
})
|
|
131
131
|
|
|
132
132
|
it('handles app:addmarker safely', () => {
|
|
@@ -137,7 +137,7 @@ describe('useMarkers', () => {
|
|
|
137
137
|
act(() => handleAddMarker(addPayload))
|
|
138
138
|
expect(mockDispatch).toHaveBeenCalledWith({
|
|
139
139
|
type: 'UPSERT_LOCATION_MARKER',
|
|
140
|
-
payload: { id: 'm1', coords: { lat: 1, lng: 1 }, label: 'Test', x: 200, y:
|
|
140
|
+
payload: { id: 'm1', coords: { lat: 1, lng: 1 }, label: 'Test', x: 200, y: 400, isVisible: true }
|
|
141
141
|
})
|
|
142
142
|
})
|
|
143
143
|
|
|
@@ -10,6 +10,7 @@ import { Attributions } from '../components/Attributions/Attributions'
|
|
|
10
10
|
import { layoutSlots } from '../renderer/slots'
|
|
11
11
|
import { SlotRenderer } from '../renderer/SlotRenderer'
|
|
12
12
|
import { HtmlElementHost } from '../renderer/HtmlElementHost'
|
|
13
|
+
import { getMapThemeVars } from '../../config/mapTheme.js'
|
|
13
14
|
|
|
14
15
|
// eslint-disable-next-line camelcase, react/jsx-pascal-case
|
|
15
16
|
// sonarjs/disable-next-line function-name
|
|
@@ -30,10 +31,9 @@ export const Layout = () => {
|
|
|
30
31
|
`im-o-app--${interfaceType}`,
|
|
31
32
|
`im-o-app--${isFullscreen ? 'fullscreen' : 'inline'}`,
|
|
32
33
|
`im-o-app--${mapStyle?.appColorScheme || preferredColorScheme}-app`,
|
|
33
|
-
`im-o-app--${mapStyle?.mapColorScheme || 'light'}-map`,
|
|
34
34
|
hasExclusiveControl && 'im-o-app--exclusive-control'
|
|
35
35
|
].filter(Boolean).join(' ')}
|
|
36
|
-
style={{ backgroundColor: mapStyle?.backgroundColor || undefined }}
|
|
36
|
+
style={{ backgroundColor: mapStyle?.backgroundColor || undefined, ...getMapThemeVars(mapStyle) }}
|
|
37
37
|
ref={layoutRefs.appContainerRef}
|
|
38
38
|
>
|
|
39
39
|
<Viewport keyboardHintPortalRef={layoutRefs.topRef} />
|
|
@@ -82,19 +82,24 @@ export const Layout = () => {
|
|
|
82
82
|
<SlotRenderer slot={layoutSlots.RIGHT_BOTTOM} />
|
|
83
83
|
</div>
|
|
84
84
|
</div>
|
|
85
|
-
<div className='im-o-
|
|
86
|
-
<div className='im-o-
|
|
85
|
+
<div className='im-o-app__bottom' ref={layoutRefs.bottomRef}>
|
|
86
|
+
<div className='im-o-app__bottom-col'>
|
|
87
87
|
<Logo />
|
|
88
|
+
<div className='im-o-app__bottom-left'>
|
|
89
|
+
<SlotRenderer slot={layoutSlots.BOTTOM_LEFT} />
|
|
90
|
+
</div>
|
|
88
91
|
</div>
|
|
89
|
-
<div className='im-o-
|
|
90
|
-
<
|
|
91
|
-
|
|
92
|
+
<div className='im-o-app__bottom-col'>
|
|
93
|
+
<div className='im-o-app__bottom-right' ref={layoutRefs.bottomRightRef}>
|
|
94
|
+
<SlotRenderer slot={layoutSlots.BOTTOM_RIGHT} />
|
|
95
|
+
</div>
|
|
96
|
+
<div className='im-o-app__attributions' ref={layoutRefs.attributionsRef}>
|
|
92
97
|
<Attributions />
|
|
93
98
|
</div>
|
|
94
99
|
</div>
|
|
95
100
|
</div>
|
|
96
|
-
<div className='im-o-
|
|
97
|
-
<SlotRenderer slot={layoutSlots.
|
|
101
|
+
<div className='im-o-app__drawer' ref={layoutRefs.drawerRef}>
|
|
102
|
+
<SlotRenderer slot={layoutSlots.DRAWER} />
|
|
98
103
|
</div>
|
|
99
104
|
<div className='im-o-app__actions' ref={layoutRefs.actionsRef}>
|
|
100
105
|
<SlotRenderer slot={layoutSlots.ACTIONS} />
|
|
@@ -38,7 +38,7 @@ describe('Layout', () => {
|
|
|
38
38
|
topLeftColRef: React.createRef(),
|
|
39
39
|
topRightColRef: React.createRef(),
|
|
40
40
|
rightRef: React.createRef(),
|
|
41
|
-
|
|
41
|
+
bottomRef: React.createRef(),
|
|
42
42
|
actionsRef: React.createRef()
|
|
43
43
|
}
|
|
44
44
|
|
|
@@ -72,9 +72,11 @@ describe('Layout', () => {
|
|
|
72
72
|
expect(root.className).toContain('im-o-app--map')
|
|
73
73
|
expect(root.className).toContain('im-o-app--inline')
|
|
74
74
|
expect(root.className).toContain('im-o-app--light-app')
|
|
75
|
-
expect(root.className).toContain('im-o-app--dark-map')
|
|
76
75
|
expect(root.className).toContain('im-o-app--exclusive-control')
|
|
77
76
|
expect(root.style.backgroundColor).toBe('pink')
|
|
77
|
+
expect(root.style.getPropertyValue('--map-overlay-halo-color')).toBe('#0b0c0c')
|
|
78
|
+
expect(root.style.getPropertyValue('--map-overlay-selected-color')).toBe('#ffffff')
|
|
79
|
+
expect(root.style.getPropertyValue('--map-overlay-foreground-color')).toBe('#ffffff')
|
|
78
80
|
|
|
79
81
|
const overlay = root.querySelector('.im-o-app__overlay')
|
|
80
82
|
expect(overlay.className).not.toContain('not-ready')
|
|
@@ -86,7 +88,7 @@ describe('Layout', () => {
|
|
|
86
88
|
expect(screen.getByTestId('slot-side')).toBeInTheDocument()
|
|
87
89
|
expect(screen.getByTestId('slot-banner')).toBeInTheDocument()
|
|
88
90
|
expect(screen.getByTestId('slot-top-left')).toBeInTheDocument()
|
|
89
|
-
expect(screen.getByTestId('slot-
|
|
91
|
+
expect(screen.getByTestId('slot-bottom-right')).toBeInTheDocument()
|
|
90
92
|
expect(screen.getByTestId('slot-modal')).toBeInTheDocument()
|
|
91
93
|
})
|
|
92
94
|
|
|
@@ -123,7 +125,7 @@ describe('Layout', () => {
|
|
|
123
125
|
|
|
124
126
|
const root = document.getElementById('myApp-im-app')
|
|
125
127
|
expect(root.className).toContain('im-o-app--dark-app')
|
|
126
|
-
expect(root.className).toContain('im-o-app--light-map')
|
|
128
|
+
expect(root.className).not.toContain('im-o-app--light-map')
|
|
127
129
|
expect(root.style.backgroundColor).toBe('')
|
|
128
130
|
expect(root.className).not.toContain('exclusive-control')
|
|
129
131
|
})
|