@defra/interactive-map 0.0.17-alpha → 0.0.19-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/css/docusaurus.css +58 -34
- 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/panel-definition.md +16 -0
- package/docs/api/symbol-config.md +160 -0
- package/docs/api/symbol-registry.md +115 -0
- package/docs/api.md +50 -23
- package/docs/assets/basic-map.jpg +0 -0
- package/docs/assets/button-first.jpg +0 -0
- package/docs/assets/maker-panel.jpg +0 -0
- package/docs/examples/add-marker-with-panel.mdx +59 -0
- package/docs/examples/basic-map.mdx +24 -0
- package/docs/examples/button-map.mdx +24 -0
- package/docs/examples/index.mdx +49 -0
- package/docs/index.mdx +1 -1
- package/docs/plugins/datasets.md +105 -9
- package/docs/plugins/interact.md +100 -44
- package/docs/plugins/search.md +15 -3
- package/docs/plugins.md +1 -1
- package/docusaurus.config.cjs +9 -1
- package/package.json +1 -1
- package/plugins/beta/datasets/dist/css/index.css +32 -14
- 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 +9 -4
- package/plugins/beta/datasets/src/adapters/maplibre/layerBuilders.js +57 -11
- package/plugins/beta/datasets/src/adapters/maplibre/layerIds.js +14 -8
- package/plugins/beta/datasets/src/adapters/maplibre/maplibreLayerAdapter.js +155 -53
- 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 +1 -1
- package/plugins/beta/datasets/src/api/setData.js +4 -2
- package/plugins/beta/datasets/src/api/setStyle.js +2 -2
- 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 +13 -4
- package/plugins/beta/datasets/src/defaults.js +4 -2
- package/plugins/beta/datasets/src/index.js +2 -1
- package/plugins/beta/datasets/src/manifest.js +1 -1
- package/plugins/beta/datasets/src/panels/Key.jsx +11 -89
- package/plugins/beta/datasets/src/panels/Key.module.scss +24 -13
- package/plugins/beta/datasets/src/panels/Layers.module.scss +13 -7
- package/plugins/beta/datasets/src/reducer.js +6 -0
- package/plugins/beta/datasets/src/reducers/keyReducer.js +34 -0
- package/plugins/beta/datasets/src/utils/mergeSublayer.js +8 -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 +3 -0
- 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/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/scale-bar/dist/css/index.css +1 -1
- package/plugins/beta/scale-bar/src/scaleBar.scss +1 -0
- 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 +19 -8
- package/plugins/interact/src/InteractInit.test.js +26 -6
- package/plugins/interact/src/api/clear.js +1 -1
- package/plugins/interact/src/api/enable.test.js +7 -7
- package/plugins/interact/src/api/selectMarker.js +14 -0
- package/plugins/interact/src/api/selectMarker.test.js +25 -0
- package/plugins/interact/src/api/unselectMarker.js +14 -0
- package/plugins/interact/src/api/unselectMarker.test.js +14 -0
- package/plugins/interact/src/defaults.js +4 -6
- package/plugins/interact/src/events.js +27 -36
- package/plugins/interact/src/events.test.js +119 -90
- 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/manifest.js +10 -2
- package/plugins/interact/src/reducer.js +59 -5
- package/plugins/interact/src/reducer.test.js +100 -12
- 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/interact/src/utils/interactionModes.js +12 -0
- 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/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-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 +36 -7
- package/providers/maplibre/src/utils/highlightFeatures.test.js +153 -96
- 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/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/Panel/Panel.jsx +6 -6
- package/src/App/components/Panel/Panel.test.jsx +37 -0
- package/src/App/components/Viewport/Viewport.jsx +5 -15
- package/src/App/components/Viewport/Viewport.module.scss +2 -0
- package/src/App/components/Viewport/Viewport.test.jsx +16 -33
- package/src/App/hooks/useInterfaceAPI.js +7 -7
- package/src/App/hooks/useInterfaceAPI.test.js +162 -0
- package/src/App/hooks/useLayoutMeasurements.js +64 -72
- package/src/App/hooks/useMarkersAPI.js +2 -5
- package/src/App/hooks/useMarkersAPI.test.js +4 -4
- package/src/App/layout/Layout.jsx +3 -3
- package/src/App/layout/Layout.test.jsx +4 -2
- package/src/App/layout/layout.module.scss +1 -8
- package/src/App/renderer/HtmlElementHost.jsx +10 -5
- package/src/App/renderer/mapPanels.js +2 -1
- package/src/App/store/ServiceProvider.jsx +7 -5
- package/src/App/store/appActionsMap.js +4 -4
- package/src/App/store/appActionsMap.test.js +10 -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 +59 -11
- package/src/InteractiveMap/InteractiveMap.test.js +126 -4
- package/src/InteractiveMap/domStateManager.js +18 -6
- package/src/InteractiveMap/domStateManager.test.js +21 -0
- package/src/InteractiveMap/historyManager.js +28 -16
- package/src/InteractiveMap/historyManager.test.js +17 -0
- package/src/config/appConfig.js +2 -7
- package/src/config/appConfig.test.js +4 -15
- package/src/config/defaults.js +2 -3
- package/src/config/events.js +20 -21
- package/src/config/mapTheme.js +56 -0
- package/src/config/patternConfig.js +16 -0
- package/src/config/symbolConfig.js +80 -0
- package/src/scss/settings/_colors.scss +0 -9
- package/src/services/closeApp.js +1 -10
- package/src/services/closeApp.test.js +3 -43
- 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 +99 -12
- package/src/utils/mapStateSync.js +48 -10
- package/src/utils/mapStateSync.test.js +29 -9
- 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/docs/examples.mdx +0 -70
- package/plugins/beta/datasets/src/adapters/maplibre/patternRegistry.js +0 -48
- package/plugins/beta/datasets/src/styles/patterns.js +0 -157
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { applyExclusionFilter } from '../../utils/filters.js'
|
|
2
2
|
import { getSourceId, getLayerIds, getSublayerLayerIds, getAllLayerIds } from './layerIds.js'
|
|
3
3
|
import { addDatasetLayers, addSublayerLayers } from './layerBuilders.js'
|
|
4
|
-
import {
|
|
4
|
+
import { getPatternConfigs } from './patternImages.js'
|
|
5
|
+
import { getSymbolConfigs, getSymbolImageId } from './symbolImages.js'
|
|
6
|
+
import { mergeSublayer } from '../../utils/mergeSublayer.js'
|
|
7
|
+
import { scaleFactor } from '../../../../../../src/config/appConfig.js'
|
|
5
8
|
|
|
6
9
|
/**
|
|
7
10
|
* MapLibre GL JS implementation of the LayerAdapter interface for the datasets plugin.
|
|
@@ -11,12 +14,25 @@ import { registerPatterns } from './patternRegistry.js'
|
|
|
11
14
|
* - Pattern image registration (delegated to patternRegistry)
|
|
12
15
|
* - Visibility toggling, feature filtering, style changes
|
|
13
16
|
* - Style-change recovery (re-adding layers after basemap swap)
|
|
17
|
+
*
|
|
18
|
+
* Symbol image rasterisation is delegated to the map provider via
|
|
19
|
+
* `mapProvider.registerSymbols()`, keeping this adapter free of provider internals.
|
|
14
20
|
*/
|
|
15
21
|
export default class MaplibreLayerAdapter {
|
|
16
|
-
|
|
17
|
-
|
|
22
|
+
/**
|
|
23
|
+
* @param {Object} mapProvider - Map provider instance (e.g. MapLibreProvider)
|
|
24
|
+
* @param {Object} symbolRegistry
|
|
25
|
+
* @param {Object} patternRegistry
|
|
26
|
+
*/
|
|
27
|
+
constructor (mapProvider, symbolRegistry, patternRegistry) {
|
|
28
|
+
this._mapProvider = mapProvider
|
|
29
|
+
this._map = mapProvider.map
|
|
30
|
+
this._symbolRegistry = symbolRegistry
|
|
31
|
+
this._patternRegistry = patternRegistry
|
|
18
32
|
// datasetId → sourceId, used by setData to update the correct source
|
|
19
33
|
this._datasetSourceMap = new Map()
|
|
34
|
+
// Tracks all active symbol-type layer IDs so non-symbol layers can be kept below them
|
|
35
|
+
this._symbolLayerIds = new Set()
|
|
20
36
|
}
|
|
21
37
|
|
|
22
38
|
// ─── Lifecycle ──────────────────────────────────────────────────────────────
|
|
@@ -24,12 +40,18 @@ export default class MaplibreLayerAdapter {
|
|
|
24
40
|
/**
|
|
25
41
|
* Initialise all datasets: register patterns, add layers, then wait for idle.
|
|
26
42
|
* @param {Object[]} datasets
|
|
27
|
-
* @param {
|
|
43
|
+
* @param {Object} mapStyle
|
|
28
44
|
* @returns {Promise<void>} Resolves once the map has processed all layers.
|
|
29
45
|
*/
|
|
30
|
-
async init (datasets,
|
|
31
|
-
|
|
32
|
-
|
|
46
|
+
async init (datasets, mapStyle) {
|
|
47
|
+
const mapStyleId = mapStyle.id
|
|
48
|
+
const pixelRatio = this._pixelRatio
|
|
49
|
+
await Promise.all([
|
|
50
|
+
this._mapProvider.registerPatterns(getPatternConfigs(datasets, this._patternRegistry), mapStyleId, this._patternRegistry),
|
|
51
|
+
this._mapProvider.registerSymbols(getSymbolConfigs(datasets), mapStyle, this._symbolRegistry)
|
|
52
|
+
])
|
|
53
|
+
this._symbolLayerIds.clear()
|
|
54
|
+
datasets.forEach(dataset => this._addLayers(dataset, mapStyle, pixelRatio))
|
|
33
55
|
await new Promise(resolve => this._map.once('idle', resolve))
|
|
34
56
|
}
|
|
35
57
|
|
|
@@ -58,17 +80,23 @@ export default class MaplibreLayerAdapter {
|
|
|
58
80
|
* Re-register patterns and re-add all layers after a basemap style change,
|
|
59
81
|
* then reapply cached dynamic source data and hidden-feature filters.
|
|
60
82
|
* @param {Object[]} datasets
|
|
61
|
-
* @param {
|
|
83
|
+
* @param {Object} newMapStyle
|
|
62
84
|
* @param {Object} hiddenFeatures - pluginState.hiddenFeatures
|
|
63
85
|
* @param {Map} dynamicSources - datasetId → dynamic source instance
|
|
64
86
|
* @returns {Promise<void>}
|
|
65
87
|
*/
|
|
66
|
-
async onStyleChange (datasets,
|
|
88
|
+
async onStyleChange (datasets, newMapStyle, hiddenFeatures, dynamicSources) {
|
|
67
89
|
// MapLibre wipes all sources/layers on style change — must wait for idle first
|
|
68
90
|
await new Promise(resolve => this._map.once('idle', resolve))
|
|
69
91
|
|
|
70
|
-
|
|
71
|
-
|
|
92
|
+
const newStyleId = newMapStyle.id
|
|
93
|
+
const pixelRatio = this._pixelRatio
|
|
94
|
+
await Promise.all([
|
|
95
|
+
this._mapProvider.registerPatterns(getPatternConfigs(datasets, this._patternRegistry), newStyleId, this._patternRegistry),
|
|
96
|
+
this._mapProvider.registerSymbols(getSymbolConfigs(datasets), newMapStyle, this._symbolRegistry)
|
|
97
|
+
])
|
|
98
|
+
this._symbolLayerIds.clear()
|
|
99
|
+
datasets.forEach(dataset => this._addLayers(dataset, newMapStyle, pixelRatio))
|
|
72
100
|
|
|
73
101
|
// Re-push cached data for dynamic sources
|
|
74
102
|
dynamicSources.forEach(source => source.reapply())
|
|
@@ -83,15 +111,45 @@ export default class MaplibreLayerAdapter {
|
|
|
83
111
|
})
|
|
84
112
|
}
|
|
85
113
|
|
|
114
|
+
/**
|
|
115
|
+
* Re-register symbols at the new pixel ratio and update icon-image on all symbol layers.
|
|
116
|
+
* Called when the map size changes so symbols are rasterised at the correct resolution.
|
|
117
|
+
* @param {Object[]} datasets
|
|
118
|
+
* @param {Object} mapStyle
|
|
119
|
+
* @returns {Promise<void>}
|
|
120
|
+
*/
|
|
121
|
+
async onSizeChange (datasets, mapStyle) {
|
|
122
|
+
await this._mapProvider.registerSymbols(getSymbolConfigs(datasets), mapStyle, this._symbolRegistry)
|
|
123
|
+
const pixelRatio = this._pixelRatio
|
|
124
|
+
datasets.forEach(dataset => {
|
|
125
|
+
getAllLayerIds(dataset).forEach(layerId => {
|
|
126
|
+
if (!this._symbolLayerIds.has(layerId) || !this._map.getLayer(layerId)) { return }
|
|
127
|
+
const imageId = getSymbolImageId(dataset, mapStyle, this._symbolRegistry, false, pixelRatio)
|
|
128
|
+
if (imageId) {
|
|
129
|
+
this._map.setLayoutProperty(layerId, 'icon-image', imageId)
|
|
130
|
+
}
|
|
131
|
+
})
|
|
132
|
+
dataset.sublayers?.forEach(sublayer => {
|
|
133
|
+
const { symbolLayerId } = getSublayerLayerIds(dataset.id, sublayer.id)
|
|
134
|
+
if (!this._map.getLayer(symbolLayerId)) { return }
|
|
135
|
+
const merged = mergeSublayer(dataset, sublayer)
|
|
136
|
+
const imageId = getSymbolImageId(merged, mapStyle, this._symbolRegistry, false, pixelRatio)
|
|
137
|
+
if (imageId) {
|
|
138
|
+
this._map.setLayoutProperty(symbolLayerId, 'icon-image', imageId)
|
|
139
|
+
}
|
|
140
|
+
})
|
|
141
|
+
})
|
|
142
|
+
}
|
|
143
|
+
|
|
86
144
|
// ─── Dataset operations ─────────────────────────────────────────────────────
|
|
87
145
|
|
|
88
146
|
/**
|
|
89
147
|
* Add a single dataset's source and layers to the map.
|
|
90
148
|
* @param {Object} dataset
|
|
91
|
-
* @param {
|
|
149
|
+
* @param {Object} mapStyle
|
|
92
150
|
*/
|
|
93
|
-
addDataset (dataset,
|
|
94
|
-
this._addLayers(dataset,
|
|
151
|
+
addDataset (dataset, mapStyle) {
|
|
152
|
+
this._addLayers(dataset, mapStyle, this._pixelRatio)
|
|
95
153
|
}
|
|
96
154
|
|
|
97
155
|
/**
|
|
@@ -108,6 +166,7 @@ export default class MaplibreLayerAdapter {
|
|
|
108
166
|
if (this._map.getLayer(layerId)) {
|
|
109
167
|
this._map.removeLayer(layerId)
|
|
110
168
|
}
|
|
169
|
+
this._symbolLayerIds.delete(layerId)
|
|
111
170
|
})
|
|
112
171
|
|
|
113
172
|
const sourceIsShared = allDatasets.some(d => d.id !== dataset.id && getSourceId(d) === sourceId)
|
|
@@ -141,13 +200,12 @@ export default class MaplibreLayerAdapter {
|
|
|
141
200
|
* @param {string} sublayerId
|
|
142
201
|
*/
|
|
143
202
|
showSublayer (datasetId, sublayerId) {
|
|
144
|
-
const { fillLayerId, strokeLayerId } = getSublayerLayerIds(datasetId, sublayerId)
|
|
145
|
-
|
|
146
|
-
this._map.
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}
|
|
203
|
+
const { fillLayerId, strokeLayerId, symbolLayerId } = getSublayerLayerIds(datasetId, sublayerId)
|
|
204
|
+
;[fillLayerId, strokeLayerId, symbolLayerId].forEach(layerId => {
|
|
205
|
+
if (this._map.getLayer(layerId)) {
|
|
206
|
+
this._map.setLayoutProperty(layerId, 'visibility', 'visible')
|
|
207
|
+
}
|
|
208
|
+
})
|
|
151
209
|
}
|
|
152
210
|
|
|
153
211
|
/**
|
|
@@ -156,13 +214,12 @@ export default class MaplibreLayerAdapter {
|
|
|
156
214
|
* @param {string} sublayerId
|
|
157
215
|
*/
|
|
158
216
|
hideSublayer (datasetId, sublayerId) {
|
|
159
|
-
const { fillLayerId, strokeLayerId } = getSublayerLayerIds(datasetId, sublayerId)
|
|
160
|
-
|
|
161
|
-
this._map.
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}
|
|
217
|
+
const { fillLayerId, strokeLayerId, symbolLayerId } = getSublayerLayerIds(datasetId, sublayerId)
|
|
218
|
+
;[fillLayerId, strokeLayerId, symbolLayerId].forEach(layerId => {
|
|
219
|
+
if (this._map.getLayer(layerId)) {
|
|
220
|
+
this._map.setLayoutProperty(layerId, 'visibility', 'none')
|
|
221
|
+
}
|
|
222
|
+
})
|
|
166
223
|
}
|
|
167
224
|
|
|
168
225
|
// ─── Feature operations ─────────────────────────────────────────────────────
|
|
@@ -190,42 +247,54 @@ export default class MaplibreLayerAdapter {
|
|
|
190
247
|
/**
|
|
191
248
|
* Update a dataset's style and re-render all its layers.
|
|
192
249
|
* @param {Object} dataset - Updated dataset (style changes already merged in)
|
|
193
|
-
* @param {
|
|
250
|
+
* @param {Object} mapStyle
|
|
194
251
|
* @returns {Promise<void>}
|
|
195
252
|
*/
|
|
196
|
-
async setStyle (dataset,
|
|
253
|
+
async setStyle (dataset, mapStyle) {
|
|
254
|
+
const mapStyleId = mapStyle.id
|
|
255
|
+
const pixelRatio = this._pixelRatio
|
|
197
256
|
getAllLayerIds(dataset).forEach(layerId => {
|
|
198
257
|
if (this._map.getLayer(layerId)) {
|
|
199
258
|
this._map.removeLayer(layerId)
|
|
200
259
|
}
|
|
260
|
+
this._symbolLayerIds.delete(layerId)
|
|
201
261
|
})
|
|
202
|
-
await
|
|
203
|
-
|
|
262
|
+
await Promise.all([
|
|
263
|
+
this._mapProvider.registerPatterns(getPatternConfigs([dataset], this._patternRegistry), mapStyleId, this._patternRegistry),
|
|
264
|
+
this._mapProvider.registerSymbols(getSymbolConfigs([dataset]), mapStyle, this._symbolRegistry)
|
|
265
|
+
])
|
|
266
|
+
this._addLayers(dataset, mapStyle, pixelRatio)
|
|
204
267
|
}
|
|
205
268
|
|
|
206
269
|
/**
|
|
207
270
|
* Update a single sublayer's style and re-render its layers.
|
|
208
271
|
* @param {Object} dataset - Updated dataset (sublayer style changes already merged in)
|
|
209
272
|
* @param {string} sublayerId
|
|
210
|
-
* @param {
|
|
273
|
+
* @param {Object} mapStyle
|
|
211
274
|
* @returns {Promise<void>}
|
|
212
275
|
*/
|
|
213
|
-
async setSublayerStyle (dataset, sublayerId,
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
276
|
+
async setSublayerStyle (dataset, sublayerId, mapStyle) {
|
|
277
|
+
const mapStyleId = mapStyle.id
|
|
278
|
+
const pixelRatio = this._pixelRatio
|
|
279
|
+
const { fillLayerId, strokeLayerId, symbolLayerId } = getSublayerLayerIds(dataset.id, sublayerId)
|
|
280
|
+
;[fillLayerId, strokeLayerId, symbolLayerId].forEach(layerId => {
|
|
281
|
+
if (this._map.getLayer(layerId)) {
|
|
282
|
+
this._map.removeLayer(layerId)
|
|
283
|
+
}
|
|
284
|
+
this._symbolLayerIds.delete(layerId)
|
|
285
|
+
})
|
|
221
286
|
const sublayer = dataset.sublayers?.find(s => s.id === sublayerId)
|
|
222
287
|
if (!sublayer) {
|
|
223
288
|
return
|
|
224
289
|
}
|
|
225
|
-
await
|
|
290
|
+
await Promise.all([
|
|
291
|
+
this._mapProvider.registerPatterns(getPatternConfigs([dataset], this._patternRegistry), mapStyleId, this._patternRegistry),
|
|
292
|
+
this._mapProvider.registerSymbols(getSymbolConfigs([dataset]), mapStyle, this._symbolRegistry)
|
|
293
|
+
])
|
|
226
294
|
const sourceId = this._datasetSourceMap.get(dataset.id)
|
|
227
295
|
const sourceLayer = dataset.tiles?.length ? dataset.sourceLayer : undefined
|
|
228
|
-
addSublayerLayers(this._map, dataset, sublayer, sourceId, sourceLayer,
|
|
296
|
+
addSublayerLayers(this._map, dataset, sublayer, sourceId, sourceLayer, { mapStyle, symbolRegistry: this._symbolRegistry, patternRegistry: this._patternRegistry, pixelRatio })
|
|
297
|
+
this._maintainSymbolOrdering(dataset)
|
|
229
298
|
}
|
|
230
299
|
|
|
231
300
|
/**
|
|
@@ -275,9 +344,43 @@ export default class MaplibreLayerAdapter {
|
|
|
275
344
|
|
|
276
345
|
// ─── Private ─────────────────────────────────────────────────────────────────
|
|
277
346
|
|
|
278
|
-
|
|
279
|
-
|
|
347
|
+
get _pixelRatio () {
|
|
348
|
+
return this._mapProvider.map.getPixelRatio() * (scaleFactor[this._mapProvider.mapSize] || 1)
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
_addLayers (dataset, mapStyle, pixelRatio) {
|
|
352
|
+
const sourceId = addDatasetLayers(this._map, dataset, mapStyle, this._symbolRegistry, this._patternRegistry, pixelRatio)
|
|
280
353
|
this._datasetSourceMap.set(dataset.id, sourceId)
|
|
354
|
+
this._maintainSymbolOrdering(dataset)
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
_getFirstSymbolLayerId () {
|
|
358
|
+
const style = this._map.getStyle()
|
|
359
|
+
if (!style?.layers) {
|
|
360
|
+
return null
|
|
361
|
+
}
|
|
362
|
+
const layer = style.layers.find(l => this._symbolLayerIds.has(l.id))
|
|
363
|
+
return layer?.id ?? null
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
_maintainSymbolOrdering (dataset) {
|
|
367
|
+
const layerIds = getAllLayerIds(dataset).filter(id => id && this._map.getLayer(id))
|
|
368
|
+
layerIds.forEach(id => {
|
|
369
|
+
if (this._map.getLayer(id)?.type === 'symbol') {
|
|
370
|
+
this._symbolLayerIds.add(id)
|
|
371
|
+
} else {
|
|
372
|
+
this._symbolLayerIds.delete(id)
|
|
373
|
+
}
|
|
374
|
+
})
|
|
375
|
+
const firstSymbolId = this._getFirstSymbolLayerId()
|
|
376
|
+
if (!firstSymbolId) {
|
|
377
|
+
return
|
|
378
|
+
}
|
|
379
|
+
layerIds.forEach(id => {
|
|
380
|
+
if (!this._symbolLayerIds.has(id)) {
|
|
381
|
+
this._map.moveLayer(id, firstSymbolId)
|
|
382
|
+
}
|
|
383
|
+
})
|
|
281
384
|
}
|
|
282
385
|
|
|
283
386
|
_setDatasetVisibility (datasetId, visibility) {
|
|
@@ -307,14 +410,12 @@ export default class MaplibreLayerAdapter {
|
|
|
307
410
|
})
|
|
308
411
|
return
|
|
309
412
|
}
|
|
310
|
-
const { fillLayerId, strokeLayerId } = getLayerIds(dataset)
|
|
413
|
+
const { fillLayerId, strokeLayerId, symbolLayerId } = getLayerIds(dataset)
|
|
311
414
|
const originalFilter = dataset.filter || null
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
applyExclusionFilter(this._map, strokeLayerId, originalFilter, idProperty, excludeIds)
|
|
317
|
-
}
|
|
415
|
+
const layerIds = [fillLayerId, strokeLayerId, symbolLayerId].filter(Boolean)
|
|
416
|
+
layerIds.forEach(layerId => {
|
|
417
|
+
applyExclusionFilter(this._map, layerId, originalFilter, idProperty, excludeIds)
|
|
418
|
+
})
|
|
318
419
|
}
|
|
319
420
|
|
|
320
421
|
_setPaintOpacity (layerId, opacity) {
|
|
@@ -322,7 +423,8 @@ export default class MaplibreLayerAdapter {
|
|
|
322
423
|
if (!layer) {
|
|
323
424
|
return
|
|
324
425
|
}
|
|
325
|
-
const
|
|
426
|
+
const opacityProps = { line: 'line-opacity', symbol: 'icon-opacity' }
|
|
427
|
+
const prop = opacityProps[layer.type] || 'fill-opacity'
|
|
326
428
|
this._map.setPaintProperty(layerId, prop, opacity)
|
|
327
429
|
}
|
|
328
430
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Re-export pure pattern utilities from core — no map engine dependency.
|
|
2
|
+
import { hasPattern } from '../../../../../../src/utils/patternUtils.js'
|
|
3
|
+
import { mergeSublayer } from '../../utils/mergeSublayer.js'
|
|
4
|
+
|
|
5
|
+
export { hasPattern, getPatternInnerContent, getPatternImageId, getKeyPatternPaths, injectColors } from '../../../../../../src/utils/patternUtils.js'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Returns a flat list of datasets and merged sublayers that require pattern images.
|
|
9
|
+
* Handles sublayer merging so callers (e.g. mapProvider.registerPatterns) receive ready-to-use configs.
|
|
10
|
+
*
|
|
11
|
+
* @param {Object[]} datasets
|
|
12
|
+
* @param {Object} patternRegistry
|
|
13
|
+
* @returns {Object[]}
|
|
14
|
+
*/
|
|
15
|
+
export const getPatternConfigs = (datasets, patternRegistry) =>
|
|
16
|
+
datasets.flatMap(dataset => {
|
|
17
|
+
const configs = hasPattern(dataset) ? [dataset] : []
|
|
18
|
+
if (dataset.sublayers?.length) {
|
|
19
|
+
dataset.sublayers.forEach(sublayer => {
|
|
20
|
+
const merged = mergeSublayer(dataset, sublayer)
|
|
21
|
+
if (hasPattern(merged)) {
|
|
22
|
+
configs.push(merged)
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
return configs
|
|
27
|
+
})
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Re-export pure symbol resolution utilities from core — no map engine dependency.
|
|
2
|
+
import { hasSymbol } from '../../../../../../src/utils/symbolUtils.js'
|
|
3
|
+
import { mergeSublayer } from '../../utils/mergeSublayer.js'
|
|
4
|
+
|
|
5
|
+
export { hasSymbol, getSymbolDef, getSymbolStyleColors, getSymbolViewBox, getSymbolAnchor } from '../../../../../../src/utils/symbolUtils.js'
|
|
6
|
+
|
|
7
|
+
// Re-export MapLibre-specific symbol utilities from the provider.
|
|
8
|
+
// This is the single cross-boundary import in the adapter; in a separate-package
|
|
9
|
+
// setup this would be: '@interactive-map/maplibre-provider/utils/symbolImages'
|
|
10
|
+
export { anchorToMaplibre, getSymbolImageId } from '../../../../../../providers/maplibre/src/utils/symbolImages.js'
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Returns a flat list of datasets and merged sublayers that require symbol images.
|
|
14
|
+
* Handles sublayer merging so callers (e.g. mapProvider.registerSymbols) receive ready-to-use configs.
|
|
15
|
+
*
|
|
16
|
+
* @param {Object[]} datasets
|
|
17
|
+
* @returns {Object[]}
|
|
18
|
+
*/
|
|
19
|
+
export const getSymbolConfigs = (datasets) =>
|
|
20
|
+
datasets.flatMap(dataset => {
|
|
21
|
+
const configs = hasSymbol(dataset) ? [dataset] : []
|
|
22
|
+
if (dataset.sublayers?.length) {
|
|
23
|
+
dataset.sublayers.forEach(sublayer => {
|
|
24
|
+
const merged = mergeSublayer(dataset, sublayer)
|
|
25
|
+
if (hasSymbol(merged)) {
|
|
26
|
+
configs.push(merged)
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
return configs
|
|
31
|
+
})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { datasetDefaults } from '../defaults.js'
|
|
2
2
|
|
|
3
3
|
export const addDataset = ({ pluginState, mapState }, dataset) => {
|
|
4
|
-
pluginState.layerAdapter?.addDataset({ ...datasetDefaults, ...dataset }, mapState.mapStyle
|
|
4
|
+
pluginState.layerAdapter?.addDataset({ ...datasetDefaults, ...dataset }, mapState.mapStyle)
|
|
5
5
|
pluginState.dispatch({ type: 'ADD_DATASET', payload: { dataset, datasetDefaults } })
|
|
6
6
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import { logger } from '../../../../../src/services/logger.js'
|
|
2
|
+
|
|
3
|
+
export const setData = ({ pluginState }, geojson, { datasetId }) => {
|
|
2
4
|
const dataset = pluginState.datasets?.find(d => d.id === datasetId)
|
|
3
5
|
if (dataset?.tiles) {
|
|
4
|
-
|
|
6
|
+
logger.warn(`setData called on vector tile dataset "${datasetId}" — has no effect`)
|
|
5
7
|
return
|
|
6
8
|
}
|
|
7
9
|
pluginState.layerAdapter?.setData(datasetId, geojson)
|
|
@@ -12,11 +12,11 @@ export const setStyle = ({ pluginState, mapState }, style, { datasetId, sublayer
|
|
|
12
12
|
sublayer.id === sublayerId ? { ...sublayer, style: { ...sublayer.style, ...style } } : sublayer
|
|
13
13
|
)
|
|
14
14
|
}
|
|
15
|
-
pluginState.layerAdapter?.setSublayerStyle(updatedSublayerDataset, sublayerId, mapState.mapStyle
|
|
15
|
+
pluginState.layerAdapter?.setSublayerStyle(updatedSublayerDataset, sublayerId, mapState.mapStyle)
|
|
16
16
|
return
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
pluginState.dispatch({ type: 'SET_DATASET_STYLE', payload: { datasetId, styleChanges: style } })
|
|
20
20
|
const updatedDataset = { ...dataset, ...style }
|
|
21
|
-
pluginState.layerAdapter?.setStyle(updatedDataset, mapState.mapStyle
|
|
21
|
+
pluginState.layerAdapter?.setStyle(updatedDataset, mapState.mapStyle)
|
|
22
22
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { render, screen } from '@testing-library/react'
|
|
2
|
+
import { EmptyKey } from './EmptyKey'
|
|
3
|
+
|
|
4
|
+
describe('EmptyKey', () => {
|
|
5
|
+
const text = 'No features available'
|
|
6
|
+
|
|
7
|
+
it('renders the wrapper div with the correct class', async () => {
|
|
8
|
+
const { container } = render(<EmptyKey text={text} />)
|
|
9
|
+
expect(container.querySelector('.im-c-datasets-key')).toBeTruthy()
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
it('renders the empty message paragraph with the correct class', async () => {
|
|
13
|
+
const { container } = render(<EmptyKey text={text} />)
|
|
14
|
+
expect(container.querySelector('.im-c-datasets-key__empty-message')).toBeTruthy()
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
it('renders the provided text', async () => {
|
|
18
|
+
render(<EmptyKey text={text} />)
|
|
19
|
+
expect(screen.getByText(text)).toBeTruthy()
|
|
20
|
+
})
|
|
21
|
+
})
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { hasSymbol, getSymbolDef } from '../../../../../src/utils/symbolUtils.js'
|
|
2
|
+
import { hasPattern } from '../../../../../src/utils/patternUtils.js'
|
|
3
|
+
import { KeySvgPattern } from './KeySvgPattern.jsx'
|
|
4
|
+
import { KeySvgSymbol } from './KeySvgSymbol.jsx'
|
|
5
|
+
import { KeySvgLine } from './KeySvgLine.jsx'
|
|
6
|
+
import { KeySvgRect } from './KeySvgRect.jsx'
|
|
7
|
+
|
|
8
|
+
export const KeySvg = (props) => {
|
|
9
|
+
const { symbolRegistry } = props
|
|
10
|
+
const symbolDef = hasSymbol(props) && getSymbolDef(props, symbolRegistry)
|
|
11
|
+
if (symbolDef) {
|
|
12
|
+
return <KeySvgSymbol {...props} symbolDef={symbolDef} />
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (hasPattern(props)) {
|
|
16
|
+
return <KeySvgPattern {...props} />
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (props.keySymbolShape === 'line') {
|
|
20
|
+
return <KeySvgLine {...props} />
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return <KeySvgRect {...props} />
|
|
24
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { svgProps, SVG_SIZE, SVG_CENTER } from './svgProperties.js'
|
|
2
|
+
import { getValueForStyle } from '../../../../../src/utils/getValueForStyle'
|
|
3
|
+
|
|
4
|
+
export const KeySvgLine = (props) => {
|
|
5
|
+
const { mapStyle } = props
|
|
6
|
+
return (
|
|
7
|
+
<svg {...svgProps}>
|
|
8
|
+
<line
|
|
9
|
+
x1={props.strokeWidth / 2}
|
|
10
|
+
y1={SVG_CENTER}
|
|
11
|
+
x2={SVG_SIZE - props.strokeWidth / 2}
|
|
12
|
+
y2={SVG_CENTER}
|
|
13
|
+
stroke={getValueForStyle(props.stroke, mapStyle.id)}
|
|
14
|
+
strokeWidth={props.strokeWidth}
|
|
15
|
+
strokeLinecap='round'
|
|
16
|
+
/>
|
|
17
|
+
</svg>
|
|
18
|
+
)
|
|
19
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { getKeyPatternPaths } from '../../../../../src/utils/patternUtils.js'
|
|
2
|
+
import { svgProps } from './svgProperties.js'
|
|
3
|
+
const PATTERN_INSET = 2
|
|
4
|
+
|
|
5
|
+
export const KeySvgPattern = (props) => {
|
|
6
|
+
const { patternRegistry, mapStyle } = props
|
|
7
|
+
|
|
8
|
+
const paths = getKeyPatternPaths(props, mapStyle.id, patternRegistry)
|
|
9
|
+
return (
|
|
10
|
+
<svg {...svgProps}>
|
|
11
|
+
<g dangerouslySetInnerHTML={{ __html: paths.border }} />
|
|
12
|
+
<g transform={`translate(${PATTERN_INSET}, ${PATTERN_INSET})`} dangerouslySetInnerHTML={{ __html: paths.content }} />
|
|
13
|
+
</svg>
|
|
14
|
+
)
|
|
15
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { getValueForStyle } from '../../../../../src/utils/getValueForStyle'
|
|
2
|
+
import { svgProps, SVG_SIZE } from './svgProperties.js'
|
|
3
|
+
|
|
4
|
+
export const KeySvgRect = (props) => {
|
|
5
|
+
const { mapStyle } = props
|
|
6
|
+
return (
|
|
7
|
+
<svg {...svgProps}>
|
|
8
|
+
<rect
|
|
9
|
+
x={props.strokeWidth / 2}
|
|
10
|
+
y={props.strokeWidth / 2}
|
|
11
|
+
width={SVG_SIZE - props.strokeWidth}
|
|
12
|
+
height={SVG_SIZE - props.strokeWidth}
|
|
13
|
+
rx={props.strokeWidth}
|
|
14
|
+
ry={props.strokeWidth}
|
|
15
|
+
fill={getValueForStyle(props.fill, mapStyle.id)}
|
|
16
|
+
stroke={getValueForStyle(props.stroke, mapStyle.id)}
|
|
17
|
+
strokeWidth={props.strokeWidth}
|
|
18
|
+
strokeLinejoin='round'
|
|
19
|
+
/>
|
|
20
|
+
</svg>
|
|
21
|
+
)
|
|
22
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { getSymbolStyleColors, getSymbolViewBox } from '../../../../../src/utils/symbolUtils.js'
|
|
2
|
+
import { svgSymbolProps } from './svgProperties.js'
|
|
3
|
+
|
|
4
|
+
export const KeySvgSymbol = (props) => {
|
|
5
|
+
const { symbolRegistry, mapStyle, symbolDef } = props
|
|
6
|
+
const mapColorScheme = mapStyle?.appColorScheme ?? 'light'
|
|
7
|
+
const keyMapStyle = { ...mapStyle, mapColorScheme }
|
|
8
|
+
|
|
9
|
+
const resolvedSvg = symbolRegistry.resolve(symbolDef, getSymbolStyleColors(props), keyMapStyle)
|
|
10
|
+
const viewBox = getSymbolViewBox(props, symbolDef)
|
|
11
|
+
return (
|
|
12
|
+
<svg {...svgSymbolProps} viewBox={viewBox}>
|
|
13
|
+
<g dangerouslySetInnerHTML={{ __html: resolvedSvg }} />
|
|
14
|
+
</svg>
|
|
15
|
+
)
|
|
16
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export const SVG_SIZE = 20
|
|
2
|
+
export const SVG_CENTER = SVG_SIZE / 2
|
|
3
|
+
const SVG_SYMBOL_SIZE = 38
|
|
4
|
+
|
|
5
|
+
export const svgProps = {
|
|
6
|
+
xmlns: 'http://www.w3.org/2000/svg',
|
|
7
|
+
width: SVG_SIZE,
|
|
8
|
+
height: SVG_SIZE,
|
|
9
|
+
viewBox: `0 0 ${SVG_SIZE} ${SVG_SIZE}`,
|
|
10
|
+
className: 'am-c-datasets-key-symbol',
|
|
11
|
+
'aria-hidden': 'true',
|
|
12
|
+
focusable: 'false'
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const svgSymbolProps = {
|
|
16
|
+
...svgProps,
|
|
17
|
+
width: SVG_SYMBOL_SIZE,
|
|
18
|
+
height: SVG_SYMBOL_SIZE,
|
|
19
|
+
className: 'am-c-datasets-key-symbol am-c-datasets-key-symbol--point'
|
|
20
|
+
}
|
|
@@ -11,7 +11,7 @@ export const createDatasets = ({
|
|
|
11
11
|
adapter,
|
|
12
12
|
pluginConfig,
|
|
13
13
|
pluginStateRef,
|
|
14
|
-
|
|
14
|
+
mapStyle,
|
|
15
15
|
mapProvider,
|
|
16
16
|
events,
|
|
17
17
|
eventBus
|
|
@@ -25,7 +25,7 @@ export const createDatasets = ({
|
|
|
25
25
|
|
|
26
26
|
// Initialise all datasets via the adapter, then set up dynamic sources
|
|
27
27
|
const processedDatasets = datasets.map(d => applyDatasetDefaults(d, datasetDefaults))
|
|
28
|
-
adapter.init(processedDatasets,
|
|
28
|
+
adapter.init(processedDatasets, mapStyle).then(() => {
|
|
29
29
|
processedDatasets.forEach(dataset => {
|
|
30
30
|
if (!isDynamicSource(dataset)) {
|
|
31
31
|
return
|
|
@@ -42,16 +42,25 @@ export const createDatasets = ({
|
|
|
42
42
|
eventBus.emit('datasets:ready')
|
|
43
43
|
})
|
|
44
44
|
|
|
45
|
+
let currentMapStyle = mapStyle
|
|
46
|
+
|
|
45
47
|
// Handle basemap style changes — delegate entirely to the adapter
|
|
46
|
-
const onSetStyle = (
|
|
47
|
-
|
|
48
|
+
const onSetStyle = (newMapStyle) => {
|
|
49
|
+
currentMapStyle = newMapStyle
|
|
50
|
+
adapter.onStyleChange(getDatasets(), newMapStyle, getHiddenFeatures(), dynamicSources)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const onSizeChange = () => {
|
|
54
|
+
adapter.onSizeChange(getDatasets(), currentMapStyle)
|
|
48
55
|
}
|
|
49
56
|
|
|
50
57
|
eventBus.on(events.MAP_SET_STYLE, onSetStyle)
|
|
58
|
+
eventBus.on(events.MAP_SIZE_CHANGE, onSizeChange)
|
|
51
59
|
|
|
52
60
|
return {
|
|
53
61
|
remove () {
|
|
54
62
|
eventBus.off(events.MAP_SET_STYLE, onSetStyle)
|
|
63
|
+
eventBus.off(events.MAP_SIZE_CHANGE, onSizeChange)
|
|
55
64
|
|
|
56
65
|
// Clean up dynamic sources
|
|
57
66
|
dynamicSources.forEach(source => source.destroy())
|
|
@@ -16,12 +16,14 @@ const datasetDefaults = {
|
|
|
16
16
|
const STYLE_PROPS = [
|
|
17
17
|
'stroke', 'strokeWidth', 'strokeDashArray',
|
|
18
18
|
'fill', 'fillPattern', 'fillPatternSvgContent', 'fillPatternForegroundColor', 'fillPatternBackgroundColor',
|
|
19
|
-
'opacity', 'symbolDescription', 'keySymbolShape'
|
|
19
|
+
'opacity', 'symbolDescription', 'keySymbolShape',
|
|
20
|
+
'symbol', 'symbolSvgContent', 'symbolViewBox', 'symbolAnchor',
|
|
21
|
+
'symbolBackgroundColor', 'symbolForegroundColor', 'symbolHaloWidth', 'symbolGraphic'
|
|
20
22
|
]
|
|
21
23
|
|
|
22
24
|
// Props whose presence in a style object indicates a custom visual style.
|
|
23
25
|
// When any are set, the default symbolDescription is not appropriate.
|
|
24
|
-
const VISUAL_STYLE_PROPS = ['stroke', 'fill', 'fillPattern', 'fillPatternSvgContent']
|
|
26
|
+
const VISUAL_STYLE_PROPS = ['stroke', 'fill', 'fillPattern', 'fillPatternSvgContent', 'symbol', 'symbolSvgContent']
|
|
25
27
|
|
|
26
28
|
const hasCustomVisualStyle = (style) =>
|
|
27
29
|
VISUAL_STYLE_PROPS.some(prop => prop in style)
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
// /plugins/datasets/index.js
|
|
2
2
|
import './datasets.scss'
|
|
3
3
|
|
|
4
|
-
export default function createPlugin (options = {}) {
|
|
4
|
+
export default function createPlugin (options = { }) {
|
|
5
5
|
const plugin = {
|
|
6
|
+
noKeyItemText: 'No features displayed',
|
|
6
7
|
...options,
|
|
7
8
|
id: 'datasets',
|
|
8
9
|
load: async () => {
|