@defra/interactive-map 0.0.23-alpha → 0.0.25-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/light-raster-thumb.jpg +0 -0
- package/assets/images/outdoor-raster-thumb.jpg +0 -0
- package/assets/images/road-raster-thumb.jpg +0 -0
- package/dist/css/index.css +1 -1
- package/docs/api/map-style-config.md +39 -2
- package/docs/plugins/search.md +70 -0
- package/package.json +17 -2
- 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/src/api/editFeature.js +9 -4
- package/plugins/beta/draw-ml/src/modes/createDrawMode.js +11 -3
- package/plugins/beta/scale-bar/dist/css/index.css +31 -1
- package/plugins/interact/src/hooks/useAttachEvents.test.js +3 -0
- package/plugins/search/dist/css/index.css +250 -1
- package/plugins/search/dist/esm/im-search-plugin.js +1 -1
- package/plugins/search/dist/esm/index.js +1 -1
- package/plugins/search/dist/umd/im-search-plugin.js +1 -1
- package/plugins/search/dist/umd/index.js +1 -1
- package/plugins/search/src/Search.jsx +2 -1
- package/plugins/search/src/components/Form/Form.jsx +11 -7
- package/plugins/search/src/components/Form/Form.test.jsx +23 -1
- package/plugins/search/src/datasets.js +2 -2
- package/plugins/search/src/datasets.test.js +1 -1
- package/plugins/search/src/defaults.js +7 -1
- package/plugins/search/src/events/fetchSuggestions.js +13 -10
- package/plugins/search/src/events/fetchSuggestions.test.js +14 -1
- package/plugins/search/src/events/formHandlers.js +2 -4
- package/plugins/search/src/events/formHandlers.test.js +3 -3
- package/plugins/search/src/events/inputHandlers.js +1 -1
- package/plugins/search/src/events/inputHandlers.test.js +1 -1
- package/plugins/search/src/events/suggestionHandlers.js +2 -1
- package/plugins/search/src/events/suggestionHandlers.test.js +7 -1
- package/plugins/search/src/index.js +3 -7
- package/plugins/search/src/reducer.js +10 -5
- package/plugins/search/src/reducer.test.js +2 -1
- package/plugins/search/src/utils/parseOsNamesResults.js +3 -3
- package/providers/beta/openlayers/dist/esm/im-openlayers-provider.js +1 -0
- package/providers/beta/openlayers/dist/esm/index.js +1 -0
- package/providers/beta/openlayers/dist/umd/im-openlayers-provider.js +2 -0
- package/providers/beta/openlayers/dist/umd/im-openlayers-provider.js.LICENSE.txt +1 -0
- package/providers/beta/openlayers/dist/umd/index.js +2 -0
- package/providers/beta/openlayers/dist/umd/index.js.LICENSE.txt +1 -0
- package/providers/beta/openlayers/src/appEvents.js +39 -0
- package/providers/beta/openlayers/src/appEvents.test.js +117 -0
- package/providers/beta/openlayers/src/defaults.js +36 -0
- package/providers/beta/openlayers/src/index.js +21 -0
- package/providers/beta/openlayers/src/mapEvents.js +132 -0
- package/providers/beta/openlayers/src/mapEvents.test.js +198 -0
- package/providers/beta/openlayers/src/openlayersProvider.js +249 -0
- package/providers/beta/openlayers/src/openlayersProvider.test.js +386 -0
- package/providers/beta/openlayers/src/utils/spatial.js +146 -0
- package/providers/beta/openlayers/src/utils/spatial.test.js +119 -0
- package/providers/beta/openlayers/src/utils/tileLayers.js +133 -0
- package/providers/beta/openlayers/src/utils/tileLayers.test.js +251 -0
- package/providers/beta/openlayers/src/utils/zoom.js +26 -0
- package/providers/beta/openlayers/src/utils/zoom.test.js +23 -0
- 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/src/utils/highlightFeatures.js +17 -7
- package/providers/maplibre/src/utils/highlightFeatures.test.js +17 -0
- package/providers/maplibre/src/utils/maplibreFixes.js +1 -1
- package/providers/maplibre/src/utils/patternImages.js +14 -9
- package/providers/maplibre/src/utils/patternImages.test.js +2 -1
- package/rollup.esm.mjs +14 -3
- package/src/App/hooks/useFeatureItems.test.js +1 -0
- package/src/App/hooks/useLayoutMeasurements.test.js +0 -1
- package/src/App/hooks/useMarkersAPI.test.js +1 -0
- package/src/App/hooks/useModalPanelBehaviour.test.js +2 -1
- package/src/App/layout/layout.module.scss +1 -0
- package/src/App/store/AppProvider.test.jsx +5 -0
- package/src/App/store/MapProvider.test.jsx +8 -1
- package/src/services/announcer.test.js +5 -7
- package/src/types.js +11 -1
- package/webpack.dev.mjs +14 -5
- package/webpack.umd.mjs +1 -0
|
@@ -61,14 +61,19 @@ export const addPatternsToMap = async (map, styleArray, mapStyleId, patternRegis
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
const effectiveRatio = getEffectivePixelRatio(pixelRatio)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
// Build a unique set of imagesToAdd callbacks to avoid redundant rasterisation and map.addImage calls
|
|
65
|
+
const addImages = styleArray.reduce((imagesToAdd, style) => {
|
|
66
|
+
const imageId = patternRegistry.getPatternImageId(style, mapStyleId, pixelRatio)
|
|
67
|
+
if (imageId && !imagesToAdd[imageId] && !map.hasImage(imageId)) {
|
|
68
|
+
imagesToAdd[imageId] = async () => {
|
|
69
|
+
const result = await rasterisePattern(style, mapStyleId, patternRegistry, pixelRatio)
|
|
70
|
+
if (result) {
|
|
71
|
+
map.addImage(result.imageId, result.imageData, { pixelRatio: effectiveRatio })
|
|
72
|
+
}
|
|
73
|
+
}
|
|
68
74
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}))
|
|
75
|
+
return imagesToAdd
|
|
76
|
+
}, {})
|
|
77
|
+
// Execute the unique set of addImage callbacks in parallel
|
|
78
|
+
await Promise.all(Object.values(addImages).map(addImage => addImage()))
|
|
74
79
|
}
|
|
@@ -76,7 +76,8 @@ describe('addPatternsToMap', () => {
|
|
|
76
76
|
|
|
77
77
|
it('processes multiple configs in parallel', async () => {
|
|
78
78
|
const map = makeMap()
|
|
79
|
-
patternRegistry.register('dots',
|
|
79
|
+
patternRegistry.register('dots', "fillPatternForegroundColor: '#aabbcc', fillPatternBackgroundColor: '#112233'")
|
|
80
|
+
console.log('patternRegistry.list', patternRegistry.list())
|
|
80
81
|
await addPatternsToMap(map, [{ fillPattern: 'stripes' }, { fillPattern: 'dots' }], OUTDOOR, patternRegistry)
|
|
81
82
|
expect(map.addImage).toHaveBeenCalledTimes(2)
|
|
82
83
|
})
|
package/rollup.esm.mjs
CHANGED
|
@@ -82,7 +82,7 @@ const PREACT_EXTERNALS = [
|
|
|
82
82
|
// dependency so it auto-installs for consumers and is resolved transparently.
|
|
83
83
|
const BABEL_RUNTIME_EXTERNAL = /@babel\/runtime/
|
|
84
84
|
|
|
85
|
-
const createESMConfig = (entryPath, outDir, isCore = false, manualChunks = null) => {
|
|
85
|
+
const createESMConfig = (entryPath, outDir, isCore = false, manualChunks = null, extraExternals = []) => {
|
|
86
86
|
const esmDir = path.resolve(__dirname, outDir)
|
|
87
87
|
// Use the parent dir as output.dir so CSS can be emitted to css/index.css
|
|
88
88
|
// (a sibling subdir) without Rollup 4's ban on ".." in emitted file names.
|
|
@@ -108,7 +108,8 @@ const createESMConfig = (entryPath, outDir, isCore = false, manualChunks = null)
|
|
|
108
108
|
// instance from their own node_modules rather than a 1 MB copy bundled
|
|
109
109
|
// into the provider. (UMD keeps it bundled — no bundler available there.)
|
|
110
110
|
'maplibre-gl',
|
|
111
|
-
/^@arcgis\/core
|
|
111
|
+
/^@arcgis\/core/,
|
|
112
|
+
...extraExternals
|
|
112
113
|
],
|
|
113
114
|
|
|
114
115
|
plugins: [
|
|
@@ -228,6 +229,16 @@ const ALL_BUILDS = [
|
|
|
228
229
|
outDir: 'providers/beta/esri/dist/esm',
|
|
229
230
|
manualChunks: (id) => { if (id.includes('/esriProvider')) return 'im-esri-provider' }
|
|
230
231
|
},
|
|
232
|
+
{
|
|
233
|
+
entryPath: './providers/beta/openlayers/src/index.js',
|
|
234
|
+
outDir: 'providers/beta/openlayers/dist/esm',
|
|
235
|
+
extraExternals: [/^ol\//, 'proj4'],
|
|
236
|
+
manualChunks: (id) => {
|
|
237
|
+
if (id.includes('/openlayersProvider')) {
|
|
238
|
+
return 'im-openlayers-provider'
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
},
|
|
231
242
|
|
|
232
243
|
// Plugins — each lazy-loads ./manifest.js; manualChunks names that split chunk
|
|
233
244
|
{
|
|
@@ -293,5 +304,5 @@ const buildsToRun = BUILD_TARGET
|
|
|
293
304
|
: ALL_BUILDS
|
|
294
305
|
|
|
295
306
|
export default buildsToRun.map(b =>
|
|
296
|
-
createESMConfig(b.entryPath, b.outDir, b.isCore || false, b.manualChunks || null)
|
|
307
|
+
createESMConfig(b.entryPath, b.outDir, b.isCore || false, b.manualChunks || null, b.extraExternals || [])
|
|
297
308
|
)
|
|
@@ -47,6 +47,7 @@ describe('useFeatureItems — event subscription', () => {
|
|
|
47
47
|
it('does not subscribe when eventBus is undefined', () => {
|
|
48
48
|
const spy = jest.spyOn(console, 'error').mockImplementation(() => {})
|
|
49
49
|
renderHook(() => useFeatureItems(undefined))
|
|
50
|
+
expect(spy).not.toHaveBeenCalled()
|
|
50
51
|
spy.mockRestore()
|
|
51
52
|
})
|
|
52
53
|
})
|
|
@@ -201,7 +201,6 @@ describe('useLayoutMeasurements', () => {
|
|
|
201
201
|
const { dispatch } = setup({ app: { arePluginsEvaluated: false } })
|
|
202
202
|
renderHook(() => useLayoutMeasurements())
|
|
203
203
|
expect(dispatch).not.toHaveBeenCalledWith(expect.objectContaining({ type: 'SET_SAFE_ZONE_INSET' }))
|
|
204
|
-
expect(layoutRefs => layoutRefs).toBeDefined() // no layout calculation
|
|
205
204
|
})
|
|
206
205
|
|
|
207
206
|
test('re-dispatches safe zone when arePluginsEvaluated becomes true', () => {
|
|
@@ -117,6 +117,7 @@ describe('useMarkers — markerRef and positioning', () => {
|
|
|
117
117
|
act(() => result.current.markerRef('m1')(ctx.mockElement))
|
|
118
118
|
const renderCallback = ctx.mockEventBus.on.mock.calls.find(call => call[0] === 'map:render')?.[1]
|
|
119
119
|
if (renderCallback) act(() => renderCallback())
|
|
120
|
+
expect(ctx.mockElement.style.transform).toBeUndefined()
|
|
120
121
|
})
|
|
121
122
|
|
|
122
123
|
it('updates positions on mapSize change', () => {
|
|
@@ -256,9 +256,10 @@ describe('useModalPanelBehaviour', () => {
|
|
|
256
256
|
})
|
|
257
257
|
|
|
258
258
|
it('handles null focus targets gracefully', () => {
|
|
259
|
+
refs.panel.current.focus = jest.fn()
|
|
259
260
|
render(<TestComponent />)
|
|
260
261
|
dispatchFocusIn(null)
|
|
261
|
-
expect(
|
|
262
|
+
expect(refs.panel.current.focus).not.toHaveBeenCalled()
|
|
262
263
|
})
|
|
263
264
|
})
|
|
264
265
|
|
|
@@ -82,6 +82,9 @@ describe('AppProvider', () => {
|
|
|
82
82
|
breakpointCb('sm')
|
|
83
83
|
interfaceCb('mobile')
|
|
84
84
|
})
|
|
85
|
+
|
|
86
|
+
expect(mockBreakpointDetector.subscribe).toHaveBeenCalledWith(expect.any(Function))
|
|
87
|
+
expect(detectInterface.subscribeToInterfaceChanges).toHaveBeenCalledWith(expect.any(Function))
|
|
85
88
|
})
|
|
86
89
|
|
|
87
90
|
test('handles eventBus setmode and revertmode', () => {
|
|
@@ -94,6 +97,8 @@ describe('AppProvider', () => {
|
|
|
94
97
|
mockOptions.eventBus.off('app:setmode', capturedSetMode)
|
|
95
98
|
mockOptions.eventBus.off('app:revertmode', capturedRevertMode)
|
|
96
99
|
})
|
|
100
|
+
expect(mockOptions.eventBus.on).toHaveBeenCalledWith('app:setmode', capturedSetMode)
|
|
101
|
+
expect(mockOptions.eventBus.on).toHaveBeenCalledWith('app:revertmode', capturedRevertMode)
|
|
97
102
|
})
|
|
98
103
|
|
|
99
104
|
test('provides state, dispatch, and layoutRefs via context', () => {
|
|
@@ -186,9 +186,14 @@ describe('MapProvider', () => {
|
|
|
186
186
|
})
|
|
187
187
|
|
|
188
188
|
test('handles dispatch actions correctly', () => {
|
|
189
|
+
let contextValue
|
|
190
|
+
const Child = () => {
|
|
191
|
+
contextValue = React.useContext(MapContext)
|
|
192
|
+
return null
|
|
193
|
+
}
|
|
189
194
|
render(
|
|
190
195
|
<MapProvider options={{ id: 'map1', mapSize: '100x100', eventBus: mockEventBus }}>
|
|
191
|
-
<
|
|
196
|
+
<Child />
|
|
192
197
|
</MapProvider>
|
|
193
198
|
)
|
|
194
199
|
|
|
@@ -197,5 +202,7 @@ describe('MapProvider', () => {
|
|
|
197
202
|
capturedHandlers['map:setstyle']({ id: 'style2' })
|
|
198
203
|
capturedHandlers['map:setsize']('400x400')
|
|
199
204
|
})
|
|
205
|
+
|
|
206
|
+
expect(contextValue.isMapReady).toBe(true)
|
|
200
207
|
})
|
|
201
208
|
})
|
|
@@ -24,21 +24,19 @@ describe('createAnnouncer', () => {
|
|
|
24
24
|
|
|
25
25
|
it('does nothing if mapStatusRef.current is null', () => {
|
|
26
26
|
const announceWithNull = createAnnouncer({ current: null })
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
expect(() => {
|
|
28
|
+
announceWithNull('Hello')
|
|
29
|
+
jest.advanceTimersByTime(1000)
|
|
30
|
+
}).not.toThrow()
|
|
30
31
|
})
|
|
31
32
|
|
|
32
33
|
it('returns early if mapStatusRef.current becomes null during setTimeout', () => {
|
|
33
34
|
announce('Test message', 'plugin')
|
|
34
35
|
expect(mapStatusRef.current.textContent).toBe('') // cleared immediately
|
|
35
36
|
|
|
36
|
-
// Set current to null before setTimeout fires
|
|
37
37
|
mapStatusRef.current = null
|
|
38
38
|
|
|
39
|
-
jest.advanceTimersByTime(100)
|
|
40
|
-
// Should not throw, just return early
|
|
41
|
-
expect(true).toBe(true)
|
|
39
|
+
expect(() => jest.advanceTimersByTime(100)).not.toThrow()
|
|
42
40
|
})
|
|
43
41
|
|
|
44
42
|
it('sets textContent for a plugin message immediately', () => {
|
package/src/types.js
CHANGED
|
@@ -403,8 +403,18 @@
|
|
|
403
403
|
* Falls back to `#0b0c0c` (light) or `#ffffff` (dark).
|
|
404
404
|
* Injected as the `--map-overlay-foreground-color` CSS custom property.
|
|
405
405
|
*
|
|
406
|
+
* @property {'raster' | 'ogc-vt'} [type]
|
|
407
|
+
* Tile layer type. Controls how the map provider constructs the basemap source. Omit (or leave
|
|
408
|
+
* undefined) for the default Mapbox GL vector tile path. The OpenLayers provider supports all
|
|
409
|
+
* three types, enabling raster, standard vector tile, and OGC vector tile basemaps:
|
|
410
|
+
* - `'raster'` — XYZ raster tile source; `url` should be a tile URL template.
|
|
411
|
+
* - `'ogc-vt'` — OGC API - Tiles vector tile source; `url` should point to an OGC style endpoint
|
|
412
|
+
* that returns a Mapbox GL style document. **Currently only supported by the OpenLayers provider.**
|
|
413
|
+
*
|
|
406
414
|
* @property {string} url
|
|
407
|
-
* URL
|
|
415
|
+
* URL for the style. For the default vector tile path and `'ogc-vt'`, this should be a URL that
|
|
416
|
+
* returns a Mapbox GL style document (Mapbox Style Specification). For `'raster'`, this should
|
|
417
|
+
* be an XYZ tile URL template with `{x}`, `{y}`, `{z}` placeholders.
|
|
408
418
|
*/
|
|
409
419
|
|
|
410
420
|
/**
|
package/webpack.dev.mjs
CHANGED
|
@@ -20,7 +20,9 @@ export default {
|
|
|
20
20
|
index: path.join(__dirname, 'demo/js/index.js'),
|
|
21
21
|
draw: path.join(__dirname, 'demo/js/draw.js'),
|
|
22
22
|
farming: path.join(__dirname, 'demo/js/farming.js'),
|
|
23
|
-
planning: path.join(__dirname, 'demo/js/planning.js')
|
|
23
|
+
planning: path.join(__dirname, 'demo/js/planning.js'),
|
|
24
|
+
'planning-ol': path.join(__dirname, 'demo/js/planning-ol.js'),
|
|
25
|
+
gep: path.join(__dirname, 'demo/js/gep.js')
|
|
24
26
|
},
|
|
25
27
|
output: {
|
|
26
28
|
path: path.resolve(__dirname, 'public'),
|
|
@@ -56,10 +58,10 @@ export default {
|
|
|
56
58
|
new webpack.DefinePlugin({
|
|
57
59
|
'process.env': {
|
|
58
60
|
// OS Open Zoomstack
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
OZS_OUTDOOR_URL: JSON.stringify(process.env.OZS_OUTDOOR_URL),
|
|
62
|
+
OZS_NIGHT_URL: JSON.stringify(process.env.OZS_NIGHT_URL),
|
|
63
|
+
OZS_DEUTERANOPIA_URL: JSON.stringify(process.env.OZS_DEUTERANOPIA_URL),
|
|
64
|
+
OZS_TRITANOPIA_URL: JSON.stringify(process.env.OZS_TRITANOPIA_URL),
|
|
63
65
|
// OS Vector Tile API (3857)
|
|
64
66
|
VTS_OUTDOOR_URL: JSON.stringify(process.env.VTS_OUTDOOR_URL),
|
|
65
67
|
VTS_DARK_URL: JSON.stringify(process.env.VTS_DARK_URL),
|
|
@@ -68,8 +70,15 @@ export default {
|
|
|
68
70
|
VTS_OUTDOOR_URL_27700: JSON.stringify(process.env.VTS_OUTDOOR_URL_27700),
|
|
69
71
|
VTS_DARK_URL_27700: JSON.stringify(process.env.VTS_DARK_URL_27700),
|
|
70
72
|
VTS_BLACK_AND_WHITE_URL_27700: JSON.stringify(process.env.VTS_BLACK_AND_WHITE_URL_27700),
|
|
73
|
+
// OS NGD Tiles API (OGC, 27700)
|
|
74
|
+
NGD_OUTDOOR_URL_27700: JSON.stringify(process.env.NGD_OUTDOOR_URL_27700),
|
|
75
|
+
NGD_BLACK_AND_WHITE_URL_27700: JSON.stringify(process.env.NGD_BLACK_AND_WHITE_URL_27700),
|
|
71
76
|
// Aerial photography
|
|
72
77
|
AERIAL_URL: JSON.stringify(process.env.AERIAL_URL),
|
|
78
|
+
// OS Maps API (27700 raster)
|
|
79
|
+
MAPS_OUTDOOR_URL: JSON.stringify(process.env.MAPS_OUTDOOR_URL),
|
|
80
|
+
MAPS_ROAD_URL: JSON.stringify(process.env.MAPS_ROAD_URL),
|
|
81
|
+
MAPS_LIGHT_URL: JSON.stringify(process.env.MAPS_LIGHT_URL),
|
|
73
82
|
// OS Auth
|
|
74
83
|
OS_CLIENT_ID: JSON.stringify(process.env.OS_CLIENT_ID),
|
|
75
84
|
OS_CLIENT_SECRET: JSON.stringify(process.env.OS_CLIENT_SECRET),
|
package/webpack.umd.mjs
CHANGED
|
@@ -137,6 +137,7 @@ const ALL_BUILDS = [
|
|
|
137
137
|
// Providers
|
|
138
138
|
{ entryPath: './providers/maplibre/src/index.js', libraryPath: 'maplibreProvider', outDir: 'providers/maplibre/dist/umd' },
|
|
139
139
|
{ entryPath: './providers/beta/open-names/src/index.js', libraryPath: 'openNamesProvider', outDir: 'providers/beta/open-names/dist/umd' },
|
|
140
|
+
{ entryPath: './providers/beta/openlayers/src/index.js', libraryPath: 'openLayersProvider', outDir: 'providers/beta/openlayers/dist/umd' },
|
|
140
141
|
|
|
141
142
|
// Plugins
|
|
142
143
|
{ entryPath: './plugins/beta/scale-bar/src/index.js', libraryPath: 'scaleBarPlugin', outDir: 'plugins/beta/scale-bar/dist/umd' },
|