@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
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
import { applyExclusionFilter } from '../../utils/filters.js'
|
|
2
|
+
import { getSourceId, getLayerIds, getSublayerLayerIds, getAllLayerIds } from './layerIds.js'
|
|
3
|
+
import { addDatasetLayers, addSublayerLayers } from './layerBuilders.js'
|
|
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'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* MapLibre GL JS implementation of the LayerAdapter interface for the datasets plugin.
|
|
11
|
+
*
|
|
12
|
+
* Owns all map-framework-specific concerns:
|
|
13
|
+
* - Source and layer creation (delegated to layerBuilders)
|
|
14
|
+
* - Pattern image registration (delegated to patternRegistry)
|
|
15
|
+
* - Visibility toggling, feature filtering, style changes
|
|
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.
|
|
20
|
+
*/
|
|
21
|
+
export default class MaplibreLayerAdapter {
|
|
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
|
|
32
|
+
// datasetId → sourceId, used by setData to update the correct source
|
|
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()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// ─── Lifecycle ──────────────────────────────────────────────────────────────
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Initialise all datasets: register patterns, add layers, then wait for idle.
|
|
42
|
+
* @param {Object[]} datasets
|
|
43
|
+
* @param {Object} mapStyle
|
|
44
|
+
* @returns {Promise<void>} Resolves once the map has processed all layers.
|
|
45
|
+
*/
|
|
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))
|
|
55
|
+
await new Promise(resolve => this._map.once('idle', resolve))
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Remove all layers and sources for the given datasets.
|
|
60
|
+
* @param {Object[]} datasets
|
|
61
|
+
*/
|
|
62
|
+
destroy (datasets) {
|
|
63
|
+
const removedSourceIds = new Set()
|
|
64
|
+
datasets.forEach(dataset => {
|
|
65
|
+
const sourceId = getSourceId(dataset)
|
|
66
|
+
this._getLayersUsingSource(sourceId).forEach(layerId => {
|
|
67
|
+
if (this._map.getLayer(layerId)) {
|
|
68
|
+
this._map.removeLayer(layerId)
|
|
69
|
+
}
|
|
70
|
+
})
|
|
71
|
+
if (!removedSourceIds.has(sourceId) && this._map.getSource(sourceId)) {
|
|
72
|
+
this._map.removeSource(sourceId)
|
|
73
|
+
removedSourceIds.add(sourceId)
|
|
74
|
+
}
|
|
75
|
+
})
|
|
76
|
+
this._datasetSourceMap.clear()
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Re-register patterns and re-add all layers after a basemap style change,
|
|
81
|
+
* then reapply cached dynamic source data and hidden-feature filters.
|
|
82
|
+
* @param {Object[]} datasets
|
|
83
|
+
* @param {Object} newMapStyle
|
|
84
|
+
* @param {Object} hiddenFeatures - pluginState.hiddenFeatures
|
|
85
|
+
* @param {Map} dynamicSources - datasetId → dynamic source instance
|
|
86
|
+
* @returns {Promise<void>}
|
|
87
|
+
*/
|
|
88
|
+
async onStyleChange (datasets, newMapStyle, hiddenFeatures, dynamicSources) {
|
|
89
|
+
// MapLibre wipes all sources/layers on style change — must wait for idle first
|
|
90
|
+
await new Promise(resolve => this._map.once('idle', resolve))
|
|
91
|
+
|
|
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))
|
|
100
|
+
|
|
101
|
+
// Re-push cached data for dynamic sources
|
|
102
|
+
dynamicSources.forEach(source => source.reapply())
|
|
103
|
+
|
|
104
|
+
// Reapply hidden feature filters
|
|
105
|
+
Object.entries(hiddenFeatures).forEach(([datasetId, { idProperty, ids }]) => {
|
|
106
|
+
const dataset = datasets.find(d => d.id === datasetId)
|
|
107
|
+
if (!dataset) {
|
|
108
|
+
return
|
|
109
|
+
}
|
|
110
|
+
this._applyFeatureFilter(dataset, idProperty, ids)
|
|
111
|
+
})
|
|
112
|
+
}
|
|
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
|
+
|
|
144
|
+
// ─── Dataset operations ─────────────────────────────────────────────────────
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Add a single dataset's source and layers to the map.
|
|
148
|
+
* @param {Object} dataset
|
|
149
|
+
* @param {Object} mapStyle
|
|
150
|
+
*/
|
|
151
|
+
addDataset (dataset, mapStyle) {
|
|
152
|
+
this._addLayers(dataset, mapStyle, this._pixelRatio)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Remove a dataset's layers and source from the map.
|
|
157
|
+
* Shared sources (same tiles URL or geojson URL used by multiple datasets) are
|
|
158
|
+
* only removed when no other remaining dataset references them.
|
|
159
|
+
* @param {Object} dataset
|
|
160
|
+
* @param {Object[]} allDatasets - Full current dataset list, for shared-source check.
|
|
161
|
+
*/
|
|
162
|
+
removeDataset (dataset, allDatasets) {
|
|
163
|
+
const sourceId = getSourceId(dataset)
|
|
164
|
+
|
|
165
|
+
getAllLayerIds(dataset).forEach(layerId => {
|
|
166
|
+
if (this._map.getLayer(layerId)) {
|
|
167
|
+
this._map.removeLayer(layerId)
|
|
168
|
+
}
|
|
169
|
+
this._symbolLayerIds.delete(layerId)
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
const sourceIsShared = allDatasets.some(d => d.id !== dataset.id && getSourceId(d) === sourceId)
|
|
173
|
+
|
|
174
|
+
if (!sourceIsShared && this._map.getSource(sourceId)) {
|
|
175
|
+
this._map.removeSource(sourceId)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
this._datasetSourceMap.delete(dataset.id)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Make a dataset's layers visible.
|
|
183
|
+
* @param {string} datasetId
|
|
184
|
+
*/
|
|
185
|
+
showDataset (datasetId) {
|
|
186
|
+
this._setDatasetVisibility(datasetId, 'visible')
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Hide a dataset's layers.
|
|
191
|
+
* @param {string} datasetId
|
|
192
|
+
*/
|
|
193
|
+
hideDataset (datasetId) {
|
|
194
|
+
this._setDatasetVisibility(datasetId, 'none')
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Make a single sublayer's layers visible.
|
|
199
|
+
* @param {string} datasetId
|
|
200
|
+
* @param {string} sublayerId
|
|
201
|
+
*/
|
|
202
|
+
showSublayer (datasetId, sublayerId) {
|
|
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
|
+
})
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Hide a single sublayer's layers.
|
|
213
|
+
* @param {string} datasetId
|
|
214
|
+
* @param {string} sublayerId
|
|
215
|
+
*/
|
|
216
|
+
hideSublayer (datasetId, sublayerId) {
|
|
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
|
+
})
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// ─── Feature operations ─────────────────────────────────────────────────────
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Show previously hidden features by updating the layer exclusion filter.
|
|
229
|
+
* @param {Object} dataset
|
|
230
|
+
* @param {string} idProperty
|
|
231
|
+
* @param {Array} remainingHiddenIds - IDs that should remain hidden after this call.
|
|
232
|
+
*/
|
|
233
|
+
showFeatures (dataset, idProperty, remainingHiddenIds) {
|
|
234
|
+
this._applyFeatureFilter(dataset, idProperty, remainingHiddenIds)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Hide features by updating the layer exclusion filter.
|
|
239
|
+
* @param {Object} dataset
|
|
240
|
+
* @param {string} idProperty
|
|
241
|
+
* @param {Array} allHiddenIds - Full set of IDs to hide (existing + new).
|
|
242
|
+
*/
|
|
243
|
+
hideFeatures (dataset, idProperty, allHiddenIds) {
|
|
244
|
+
this._applyFeatureFilter(dataset, idProperty, allHiddenIds)
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Update a dataset's style and re-render all its layers.
|
|
249
|
+
* @param {Object} dataset - Updated dataset (style changes already merged in)
|
|
250
|
+
* @param {Object} mapStyle
|
|
251
|
+
* @returns {Promise<void>}
|
|
252
|
+
*/
|
|
253
|
+
async setStyle (dataset, mapStyle) {
|
|
254
|
+
const mapStyleId = mapStyle.id
|
|
255
|
+
const pixelRatio = this._pixelRatio
|
|
256
|
+
getAllLayerIds(dataset).forEach(layerId => {
|
|
257
|
+
if (this._map.getLayer(layerId)) {
|
|
258
|
+
this._map.removeLayer(layerId)
|
|
259
|
+
}
|
|
260
|
+
this._symbolLayerIds.delete(layerId)
|
|
261
|
+
})
|
|
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)
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Update a single sublayer's style and re-render its layers.
|
|
271
|
+
* @param {Object} dataset - Updated dataset (sublayer style changes already merged in)
|
|
272
|
+
* @param {string} sublayerId
|
|
273
|
+
* @param {Object} mapStyle
|
|
274
|
+
* @returns {Promise<void>}
|
|
275
|
+
*/
|
|
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
|
+
})
|
|
286
|
+
const sublayer = dataset.sublayers?.find(s => s.id === sublayerId)
|
|
287
|
+
if (!sublayer) {
|
|
288
|
+
return
|
|
289
|
+
}
|
|
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
|
+
])
|
|
294
|
+
const sourceId = this._datasetSourceMap.get(dataset.id)
|
|
295
|
+
const sourceLayer = dataset.tiles?.length ? dataset.sourceLayer : undefined
|
|
296
|
+
addSublayerLayers(this._map, dataset, sublayer, sourceId, sourceLayer, { mapStyle, symbolRegistry: this._symbolRegistry, patternRegistry: this._patternRegistry, pixelRatio })
|
|
297
|
+
this._maintainSymbolOrdering(dataset)
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Set opacity for all layers belonging to a dataset.
|
|
302
|
+
* Uses setPaintProperty directly — safe to call on every slider tick.
|
|
303
|
+
* @param {string} datasetId
|
|
304
|
+
* @param {number} opacity
|
|
305
|
+
*/
|
|
306
|
+
setOpacity (datasetId, opacity) {
|
|
307
|
+
const style = this._map.getStyle()
|
|
308
|
+
if (!style?.layers) {
|
|
309
|
+
return
|
|
310
|
+
}
|
|
311
|
+
style.layers
|
|
312
|
+
.filter(layer => layer.id === datasetId || layer.id.startsWith(`${datasetId}-`))
|
|
313
|
+
.forEach(layer => this._setPaintOpacity(layer.id, opacity))
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Set opacity for a single sublayer's fill and stroke layers.
|
|
318
|
+
* Uses setPaintProperty directly — safe to call on every slider tick.
|
|
319
|
+
* @param {string} datasetId
|
|
320
|
+
* @param {string} sublayerId
|
|
321
|
+
* @param {number} opacity
|
|
322
|
+
*/
|
|
323
|
+
setSublayerOpacity (datasetId, sublayerId, opacity) {
|
|
324
|
+
const { fillLayerId, strokeLayerId } = getSublayerLayerIds(datasetId, sublayerId)
|
|
325
|
+
this._setPaintOpacity(fillLayerId, opacity)
|
|
326
|
+
this._setPaintOpacity(strokeLayerId, opacity)
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Update the GeoJSON data for a dataset's source.
|
|
331
|
+
* @param {string} datasetId
|
|
332
|
+
* @param {Object} geojson - GeoJSON FeatureCollection
|
|
333
|
+
*/
|
|
334
|
+
setData (datasetId, geojson) {
|
|
335
|
+
const sourceId = this._datasetSourceMap.get(datasetId)
|
|
336
|
+
if (!sourceId) {
|
|
337
|
+
return
|
|
338
|
+
}
|
|
339
|
+
const source = this._map.getSource(sourceId)
|
|
340
|
+
if (source && typeof source.setData === 'function') {
|
|
341
|
+
source.setData(geojson)
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// ─── Private ─────────────────────────────────────────────────────────────────
|
|
346
|
+
|
|
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)
|
|
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
|
+
})
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
_setDatasetVisibility (datasetId, visibility) {
|
|
387
|
+
const style = this._map.getStyle()
|
|
388
|
+
if (!style?.layers) {
|
|
389
|
+
return
|
|
390
|
+
}
|
|
391
|
+
// Covers base fill layer (datasetId) and all suffixed layers
|
|
392
|
+
// (-stroke, -${sublayerId}, -${sublayerId}-stroke) without needing the dataset object.
|
|
393
|
+
style.layers
|
|
394
|
+
.filter(layer =>
|
|
395
|
+
layer.id === datasetId ||
|
|
396
|
+
layer.id.startsWith(`${datasetId}-`)
|
|
397
|
+
)
|
|
398
|
+
.forEach(layer => this._map.setLayoutProperty(layer.id, 'visibility', visibility))
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
_applyFeatureFilter (dataset, idProperty, excludeIds) {
|
|
402
|
+
if (dataset.sublayers?.length) {
|
|
403
|
+
dataset.sublayers.forEach(sublayer => {
|
|
404
|
+
const { fillLayerId: subFillId, strokeLayerId: subStrokeId } = getSublayerLayerIds(dataset.id, sublayer.id)
|
|
405
|
+
const sublayerFilter = dataset.filter && sublayer.filter
|
|
406
|
+
? ['all', dataset.filter, sublayer.filter]
|
|
407
|
+
: (sublayer.filter || dataset.filter || null)
|
|
408
|
+
applyExclusionFilter(this._map, subFillId, sublayerFilter, idProperty, excludeIds)
|
|
409
|
+
applyExclusionFilter(this._map, subStrokeId, sublayerFilter, idProperty, excludeIds)
|
|
410
|
+
})
|
|
411
|
+
return
|
|
412
|
+
}
|
|
413
|
+
const { fillLayerId, strokeLayerId, symbolLayerId } = getLayerIds(dataset)
|
|
414
|
+
const originalFilter = dataset.filter || null
|
|
415
|
+
const layerIds = [fillLayerId, strokeLayerId, symbolLayerId].filter(Boolean)
|
|
416
|
+
layerIds.forEach(layerId => {
|
|
417
|
+
applyExclusionFilter(this._map, layerId, originalFilter, idProperty, excludeIds)
|
|
418
|
+
})
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
_setPaintOpacity (layerId, opacity) {
|
|
422
|
+
const layer = this._map.getLayer(layerId)
|
|
423
|
+
if (!layer) {
|
|
424
|
+
return
|
|
425
|
+
}
|
|
426
|
+
const opacityProps = { line: 'line-opacity', symbol: 'icon-opacity' }
|
|
427
|
+
const prop = opacityProps[layer.type] || 'fill-opacity'
|
|
428
|
+
this._map.setPaintProperty(layerId, prop, opacity)
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
_getLayersUsingSource (sourceId) {
|
|
432
|
+
const style = this._map.getStyle()
|
|
433
|
+
if (!style?.layers) {
|
|
434
|
+
return []
|
|
435
|
+
}
|
|
436
|
+
return style.layers
|
|
437
|
+
.filter(layer => layer.source === sourceId)
|
|
438
|
+
.map(layer => layer.id)
|
|
439
|
+
}
|
|
440
|
+
}
|
|
@@ -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,12 +1,6 @@
|
|
|
1
1
|
import { datasetDefaults } from '../defaults.js'
|
|
2
|
-
import { addMapLayers } from '../mapLayers.js'
|
|
3
2
|
|
|
4
|
-
export const addDataset = ({
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
// Add source and layers to the map
|
|
8
|
-
addMapLayers(map, mapState.mapStyle.id, { ...datasetDefaults, ...dataset })
|
|
9
|
-
|
|
10
|
-
// Update state
|
|
3
|
+
export const addDataset = ({ pluginState, mapState }, dataset) => {
|
|
4
|
+
pluginState.layerAdapter?.addDataset({ ...datasetDefaults, ...dataset }, mapState.mapStyle)
|
|
11
5
|
pluginState.dispatch({ type: 'ADD_DATASET', payload: { dataset, datasetDefaults } })
|
|
12
6
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const getOpacity = ({ pluginState }, options) => {
|
|
2
|
+
const { datasetId, sublayerId } = options || {}
|
|
3
|
+
|
|
4
|
+
if (sublayerId) {
|
|
5
|
+
const dataset = pluginState.datasets?.find(d => d.id === datasetId)
|
|
6
|
+
const sublayer = dataset?.sublayers?.find(s => s.id === sublayerId)
|
|
7
|
+
return sublayer?.style?.opacity ?? null
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (datasetId) {
|
|
11
|
+
const dataset = pluginState.datasets?.find(d => d.id === datasetId)
|
|
12
|
+
return dataset?.opacity ?? null
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Global — return first dataset's opacity
|
|
16
|
+
return pluginState.datasets?.[0]?.opacity ?? null
|
|
17
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const getStyle = ({ pluginState }, { datasetId, sublayerId } = {}) => {
|
|
2
|
+
const dataset = pluginState.datasets?.find(d => d.id === datasetId)
|
|
3
|
+
if (!dataset) {
|
|
4
|
+
return null
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
if (sublayerId) {
|
|
8
|
+
const sublayer = dataset.sublayers?.find(s => s.id === sublayerId)
|
|
9
|
+
return sublayer?.style ?? null
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return dataset.style ?? null
|
|
13
|
+
}
|
|
@@ -1,51 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const getLayerIds = (dataset) => {
|
|
4
|
-
const hasFill = !!dataset.fill
|
|
5
|
-
const hasStroke = !!dataset.stroke
|
|
6
|
-
|
|
7
|
-
const fillLayerId = hasFill ? dataset.id : null
|
|
8
|
-
let strokeLayerId = null
|
|
9
|
-
if (hasStroke) {
|
|
10
|
-
if (hasFill) {
|
|
11
|
-
strokeLayerId = `${dataset.id}-stroke`
|
|
12
|
-
} else {
|
|
13
|
-
strokeLayerId = dataset.id
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
return { fillLayerId, strokeLayerId }
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export const removeDataset = ({ mapProvider, pluginState }, datasetId) => {
|
|
21
|
-
const map = mapProvider.map
|
|
22
|
-
|
|
23
|
-
// Find the dataset
|
|
1
|
+
export const removeDataset = ({ pluginState }, datasetId) => {
|
|
24
2
|
const dataset = pluginState.datasets?.find(d => d.id === datasetId)
|
|
25
3
|
if (!dataset) {
|
|
26
4
|
return
|
|
27
5
|
}
|
|
28
6
|
|
|
29
|
-
|
|
30
|
-
const { fillLayerId, strokeLayerId } = getLayerIds(dataset)
|
|
31
|
-
const sourceId = getSourceId(dataset)
|
|
32
|
-
|
|
33
|
-
// Remove layers first
|
|
34
|
-
const layerIdsToRemove = [strokeLayerId, fillLayerId]
|
|
35
|
-
layerIdsToRemove.forEach(layerId => {
|
|
36
|
-
if (layerId && map.getLayer(layerId)) {
|
|
37
|
-
map.removeLayer(layerId)
|
|
38
|
-
}
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
// Remove source if no other datasets use it
|
|
42
|
-
const otherDatasetsUseSource = pluginState.datasets?.some(
|
|
43
|
-
d => d.id !== datasetId && getSourceId(d) === sourceId
|
|
44
|
-
)
|
|
45
|
-
if (!otherDatasetsUseSource && map.getSource(sourceId)) {
|
|
46
|
-
map.removeSource(sourceId)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Update plugin state
|
|
7
|
+
pluginState.layerAdapter?.removeDataset(dataset, pluginState.datasets)
|
|
50
8
|
pluginState.dispatch({ type: 'REMOVE_DATASET', payload: { id: datasetId } })
|
|
51
9
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { logger } from '../../../../../src/services/logger.js'
|
|
2
|
+
|
|
3
|
+
export const setData = ({ pluginState }, geojson, { datasetId }) => {
|
|
4
|
+
const dataset = pluginState.datasets?.find(d => d.id === datasetId)
|
|
5
|
+
if (dataset?.tiles) {
|
|
6
|
+
logger.warn(`setData called on vector tile dataset "${datasetId}" — has no effect`)
|
|
7
|
+
return
|
|
8
|
+
}
|
|
9
|
+
pluginState.layerAdapter?.setData(datasetId, geojson)
|
|
10
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export const setDatasetVisibility = ({ pluginState }, visible, options = {}) => {
|
|
2
|
+
const { datasetId, sublayerId } = options
|
|
3
|
+
|
|
4
|
+
if (sublayerId) {
|
|
5
|
+
const visibility = visible ? 'visible' : 'hidden'
|
|
6
|
+
pluginState.layerAdapter?.[visible ? 'showSublayer' : 'hideSublayer'](datasetId, sublayerId)
|
|
7
|
+
pluginState.dispatch({ type: 'SET_SUBLAYER_VISIBILITY', payload: { datasetId, sublayerId, visibility } })
|
|
8
|
+
return
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (datasetId) {
|
|
12
|
+
pluginState.layerAdapter?.[visible ? 'showDataset' : 'hideDataset'](datasetId)
|
|
13
|
+
pluginState.dispatch({ type: 'SET_DATASET_VISIBILITY', payload: { id: datasetId, visibility: visible ? 'visible' : 'hidden' } })
|
|
14
|
+
if (visible) {
|
|
15
|
+
const dataset = pluginState.datasets?.find(d => d.id === datasetId)
|
|
16
|
+
Object.entries(dataset?.sublayerVisibility || {}).forEach(([subId, vis]) => {
|
|
17
|
+
if (vis === 'hidden') {
|
|
18
|
+
pluginState.layerAdapter?.hideSublayer(datasetId, subId)
|
|
19
|
+
}
|
|
20
|
+
})
|
|
21
|
+
}
|
|
22
|
+
return
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Global
|
|
26
|
+
pluginState.dispatch({ type: 'SET_GLOBAL_VISIBILITY', payload: { visibility: visible ? 'visible' : 'hidden' } })
|
|
27
|
+
pluginState.datasets?.forEach(dataset => {
|
|
28
|
+
pluginState.layerAdapter?.[visible ? 'showDataset' : 'hideDataset'](dataset.id)
|
|
29
|
+
if (visible) {
|
|
30
|
+
Object.entries(dataset.sublayerVisibility || {}).forEach(([subId, vis]) => {
|
|
31
|
+
if (vis === 'hidden') {
|
|
32
|
+
pluginState.layerAdapter?.hideSublayer(dataset.id, subId)
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const setFeatureVisibility = ({ pluginState }, visible, featureIds, { datasetId, idProperty = null } = {}) => {
|
|
2
|
+
const dataset = pluginState.datasets?.find(d => d.id === datasetId)
|
|
3
|
+
if (!dataset) {
|
|
4
|
+
return
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
if (visible) {
|
|
8
|
+
const existingHidden = pluginState.hiddenFeatures[datasetId]
|
|
9
|
+
if (!existingHidden) {
|
|
10
|
+
return
|
|
11
|
+
}
|
|
12
|
+
const remainingHiddenIds = existingHidden.ids.filter(id => !featureIds.includes(id))
|
|
13
|
+
pluginState.dispatch({ type: 'SHOW_FEATURES', payload: { layerId: datasetId, featureIds } })
|
|
14
|
+
pluginState.layerAdapter?.showFeatures(dataset, idProperty, remainingHiddenIds)
|
|
15
|
+
} else {
|
|
16
|
+
const existingHidden = pluginState.hiddenFeatures[datasetId]
|
|
17
|
+
const existingIds = existingHidden?.ids || []
|
|
18
|
+
const allHiddenIds = [...new Set([...existingIds, ...featureIds])]
|
|
19
|
+
pluginState.dispatch({ type: 'HIDE_FEATURES', payload: { layerId: datasetId, idProperty, featureIds } })
|
|
20
|
+
pluginState.layerAdapter?.hideFeatures(dataset, idProperty, allHiddenIds)
|
|
21
|
+
}
|
|
22
|
+
}
|