@defra/interactive-map 0.0.8-alpha → 0.0.9-alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist/esm/im-core.js +1 -0
  2. package/dist/esm/im-shell.js +1 -0
  3. package/dist/esm/index.js +1 -2
  4. package/dist/umd/im-core.js +1 -1
  5. package/dist/umd/index.js +1 -1
  6. package/docs/api/button-definition.md +104 -3
  7. package/docs/api.md +21 -1
  8. package/docs/getting-started.md +78 -8
  9. package/package.json +31 -24
  10. package/plugins/beta/datasets/dist/css/index.css +50 -1
  11. package/plugins/beta/datasets/dist/esm/im-datasets-plugin.js +1 -0
  12. package/plugins/beta/datasets/dist/esm/index.js +1 -2
  13. package/plugins/beta/draw-es/dist/esm/im-draw-es-plugin.js +1 -0
  14. package/plugins/beta/draw-es/dist/esm/index.js +1 -2
  15. package/plugins/beta/draw-ml/dist/esm/im-draw-ml-plugin.js +1 -0
  16. package/plugins/beta/draw-ml/dist/esm/index.js +1 -2
  17. package/plugins/beta/frame/dist/css/index.css +11 -1
  18. package/plugins/beta/frame/dist/esm/im-frame-plugin.js +1 -0
  19. package/plugins/beta/frame/dist/esm/index.js +1 -2
  20. package/plugins/beta/map-styles/dist/css/index.css +79 -1
  21. package/plugins/beta/map-styles/dist/esm/im-map-styles-plugin.js +1 -0
  22. package/plugins/beta/map-styles/dist/esm/index.js +1 -2
  23. package/plugins/beta/scale-bar/dist/esm/im-scale-bar-plugin.js +1 -0
  24. package/plugins/beta/scale-bar/dist/esm/index.js +1 -2
  25. package/plugins/beta/use-location/dist/esm/im-use-location-plugin.js +1 -0
  26. package/plugins/beta/use-location/dist/esm/index.js +1 -2
  27. package/plugins/beta/use-location/dist/umd/index.js +1 -1
  28. package/plugins/interact/dist/esm/im-interact-plugin.js +1 -0
  29. package/plugins/interact/dist/esm/index.js +1 -2
  30. package/plugins/search/dist/esm/im-search-plugin.js +1 -0
  31. package/plugins/search/dist/esm/index.js +1 -2
  32. package/plugins/search/src/components/Suggestions/Suggestions.module.scss +1 -1
  33. package/plugins/search/src/search.scss +1 -1
  34. package/providers/beta/esri/dist/css/index.css +30 -1
  35. package/providers/beta/esri/dist/esm/im-esri-provider.js +1 -0
  36. package/providers/beta/esri/dist/esm/index.js +1 -2
  37. package/providers/beta/open-names/dist/esm/im-reverse-geocode.js +1 -0
  38. package/providers/beta/open-names/dist/esm/index.js +1 -2
  39. package/providers/beta/open-names/src/utils/mapToLocationModel.test.js +61 -0
  40. package/providers/maplibre/dist/esm/im-maplibre-provider.js +1 -0
  41. package/providers/maplibre/dist/esm/index.js +1 -2
  42. package/providers/maplibre/dist/umd/im-maplibre-provider.js +1 -1
  43. package/providers/maplibre/src/appEvents.test.js +44 -0
  44. package/providers/maplibre/src/index.test.js +60 -0
  45. package/providers/maplibre/src/mapEvents.test.js +115 -0
  46. package/providers/maplibre/src/maplibreProvider.test.js +205 -0
  47. package/providers/maplibre/src/utils/calculateLinearTextSize.test.js +31 -0
  48. package/providers/maplibre/src/utils/detectWebgl.test.js +63 -0
  49. package/providers/maplibre/src/utils/highlightFeatures.test.js +126 -0
  50. package/providers/maplibre/src/utils/labels.js +1 -3
  51. package/providers/maplibre/src/utils/labels.test.js +231 -0
  52. package/providers/maplibre/src/utils/maplibreFixes.test.js +66 -0
  53. package/providers/maplibre/src/utils/queryFeatures.test.js +60 -0
  54. package/providers/maplibre/src/utils/spatial.js +5 -4
  55. package/providers/maplibre/src/utils/spatial.test.js +96 -0
  56. package/rollup.esm.mjs +288 -0
  57. package/src/App/store/appActionsMap.js +1 -1
  58. package/src/InteractiveMap/InteractiveMap.js +3 -2
  59. package/webpack.dev.mjs +9 -1
  60. package/webpack.prod.mjs +8 -1
  61. package/webpack.umd.mjs +1 -2
  62. package/dist/esm/index.js.LICENSE.txt +0 -1
  63. package/plugins/beta/datasets/dist/esm/index.js.LICENSE.txt +0 -1
  64. package/plugins/beta/draw-es/dist/esm/index.js.LICENSE.txt +0 -1
  65. package/plugins/beta/draw-ml/dist/esm/index.js.LICENSE.txt +0 -1
  66. package/plugins/beta/frame/dist/esm/index.js.LICENSE.txt +0 -1
  67. package/plugins/beta/map-styles/dist/esm/index.js.LICENSE.txt +0 -1
  68. package/plugins/beta/scale-bar/dist/esm/index.js.LICENSE.txt +0 -1
  69. package/plugins/beta/use-location/dist/esm/index.js.LICENSE.txt +0 -1
  70. package/plugins/interact/dist/esm/index.js.LICENSE.txt +0 -1
  71. package/plugins/search/dist/esm/index.js.LICENSE.txt +0 -1
  72. package/providers/beta/esri/dist/esm/index.js.LICENSE.txt +0 -1
  73. package/providers/beta/open-names/dist/esm/index.js.LICENSE.txt +0 -1
  74. package/providers/maplibre/dist/esm/index.js.LICENSE.txt +0 -6
  75. package/webpack.esm.mjs +0 -154
@@ -0,0 +1,96 @@
1
+ // tests/utils/spatial.test.js
2
+ import * as spatial from '../../src/utils/spatial.js'
3
+
4
+ jest.mock('geodesy/latlon-spherical.js', () =>
5
+ jest.fn().mockImplementation((lat, lng) => ({
6
+ distanceTo: jest.fn((other) => Math.abs(lat - (other.lat || 0)) * 1609 + Math.abs(lng - (other.lon || 0)) * 1609)
7
+ }))
8
+ )
9
+
10
+ describe('spatial utils', () => {
11
+
12
+ test('formatDimension hits all branches', () => {
13
+ // < 0.5 miles
14
+ expect(spatial.formatDimension(500)).toMatch(/m$/)
15
+
16
+ // Singular mile (exactly 1.0) - hits value === 1 branch
17
+ expect(spatial.formatDimension(1609.344)).toBe('1 mile')
18
+
19
+ // 5 miles
20
+ const metersSmallMiles = 5 * 1609.344
21
+ expect(spatial.formatDimension(metersSmallMiles)).toMatch(/^5\s*miles$/)
22
+
23
+ // >= WHOLE_MILE_THRESHOLD
24
+ const metersLarge = 15 * 1609.344
25
+ expect(spatial.formatDimension(metersLarge)).toBe('15 miles')
26
+ })
27
+
28
+ test('array bounds triggers all branches', () => {
29
+ const dims = spatial.getAreaDimensions([[0, 0], [0.01, 0.02]])
30
+ expect(dims).toMatch(/by/)
31
+ })
32
+
33
+ test('LngLatBounds object triggers getWest/getSouth branch', () => {
34
+ const fakeBounds = { getWest: () => 0, getSouth: () => 0, getEast: () => 0.01, getNorth: () => 0.02 }
35
+ expect(spatial.getAreaDimensions(fakeBounds)).toMatch(/by/)
36
+ })
37
+
38
+ test('invalid bounds returns empty string', () => {
39
+ expect(spatial.getAreaDimensions(null)).toBe('')
40
+ expect(spatial.getAreaDimensions([])).toBe('')
41
+ })
42
+
43
+ test('north/south/east/west moves', () => {
44
+ expect(spatial.getCardinalMove([0,0],[0,0.5])).toMatch(/north/)
45
+ expect(spatial.getCardinalMove([0,0],[0,-0.5])).toMatch(/south/)
46
+ expect(spatial.getCardinalMove([0,0],[0.5,0])).toMatch(/east/)
47
+ expect(spatial.getCardinalMove([0,0],[-0.5,0])).toMatch(/west/)
48
+ expect(spatial.getCardinalMove([0,0],[0.5,0.5])).toMatch(/north.*east|east.*north/)
49
+ expect(spatial.getCardinalMove([0,0],[0.00001,0.00001])).toBe('')
50
+ })
51
+
52
+ test('spatialNavigate all directions and fallback', () => {
53
+ const pixels = [[0,0],[0,-1],[1,0],[0,1],[-1,0]]
54
+ expect(spatial.spatialNavigate('ArrowUp',[0,0],pixels)).toBe(1)
55
+ expect(spatial.spatialNavigate('ArrowDown',[0,0],pixels)).toBe(3)
56
+ expect(spatial.spatialNavigate('ArrowLeft',[0,0],pixels)).toBe(4)
57
+ expect(spatial.spatialNavigate('ArrowRight',[0,0],pixels)).toBe(2)
58
+ expect(spatial.spatialNavigate('InvalidDir',[0,0],pixels)).toBe(0)
59
+ })
60
+
61
+ test('spatialNavigate finds closer candidates (hits dist < minDist)', () => {
62
+ const start = [0,0]
63
+ const pixels = [[0,0],[10,0],[2,0]]
64
+ expect(spatial.spatialNavigate('ArrowRight', start, pixels)).toBe(2)
65
+ })
66
+
67
+ test('spatialNavigate skips farther candidate (dist >= minDist false branch)', () => {
68
+ // Closer candidate first → second candidate fails dist < minDist
69
+ const pixels = [[0,0],[2,0],[10,0]]
70
+ expect(spatial.spatialNavigate('ArrowRight', [0,0], pixels)).toBe(1)
71
+ })
72
+
73
+ test('spatialNavigate diagonal with dx>dy', () => {
74
+ const start = [0,0]
75
+ const pixels = [[0,0],[3,1],[1,0]] // dx>dy
76
+ expect(spatial.spatialNavigate('ArrowRight', start, pixels)).toBe(2)
77
+ })
78
+
79
+ test('getResolution returns positive value', () => {
80
+ expect(spatial.getResolution({lat:0},1)).toBeGreaterThan(0)
81
+ })
82
+
83
+ test('getPaddedBounds returns bounds', () => {
84
+ const map = {
85
+ getContainer: () => ({ getBoundingClientRect: () => ({ width:100,height:200 }) }),
86
+ getPadding: () => ({ top:1,right:2,bottom:3,left:4 }),
87
+ unproject: p => ({ x:p[0], y:p[1] })
88
+ }
89
+ const LngLatBounds = function(sw,ne){
90
+ return {sw,ne}
91
+ }
92
+ const bounds = spatial.getPaddedBounds(LngLatBounds,map)
93
+ expect(bounds.sw).toBeDefined()
94
+ expect(bounds.ne).toBeDefined()
95
+ })
96
+ })
package/rollup.esm.mjs ADDED
@@ -0,0 +1,288 @@
1
+ import path, { dirname } from 'path'
2
+ import { fileURLToPath } from 'url'
3
+ import fs from 'fs'
4
+
5
+ import { nodeResolve } from '@rollup/plugin-node-resolve'
6
+ import commonjs from '@rollup/plugin-commonjs'
7
+ import babel from '@rollup/plugin-babel'
8
+ import alias from '@rollup/plugin-alias'
9
+ import replace from '@rollup/plugin-replace'
10
+ import terser from '@rollup/plugin-terser'
11
+ import postcss from 'rollup-plugin-postcss'
12
+ import { visualizer } from 'rollup-plugin-visualizer'
13
+
14
+ const __dirname = dirname(fileURLToPath(import.meta.url))
15
+
16
+ /**
17
+ * Cleans output directories before each build starts.
18
+ * Mirrors the RemoveFilesPlugin (before) behaviour from webpack.esm.mjs.
19
+ */
20
+ const cleanPlugin = (dirs) => ({
21
+ name: 'clean',
22
+ buildStart () {
23
+ for (const dir of dirs) {
24
+ if (fs.existsSync(dir)) {
25
+ fs.rmSync(dir, { recursive: true, force: true })
26
+ }
27
+ fs.mkdirSync(dir, { recursive: true })
28
+ }
29
+ }
30
+ })
31
+
32
+ // Adds webpackChunkName magic comments to all relative dynamic imports in the
33
+ // output, deriving the name from the imported file's basename.
34
+ // Must run AFTER terser() so the comments survive minification.
35
+ // This lets webpack consumers produce named chunks matching Rollup chunk names.
36
+ const webpackChunkNamesPlugin = () => ({
37
+ name: 'webpack-chunk-names',
38
+ renderChunk (code) {
39
+ return {
40
+ // Matches import("./some-chunk-name.js") — flat relative paths only
41
+ code: code.replace(
42
+ /import\("(\.\/([^/"]+))\.js"\)/g,
43
+ (_, relPath, chunkName) => `import(/* webpackChunkName: "${chunkName}" */ "${relPath}.js")`
44
+ ),
45
+ map: null
46
+ }
47
+ }
48
+ })
49
+
50
+ /**
51
+ * Removes any *-full.css artefacts after the core build.
52
+ * Mirrors the RemoveFilesPlugin (after) behaviour from webpack.esm.mjs.
53
+ */
54
+ const removeFullCssPlugin = (cssDir) => ({
55
+ name: 'remove-full-css',
56
+ closeBundle () {
57
+ if (!fs.existsSync(cssDir)) {
58
+ return
59
+ }
60
+ fs.readdirSync(cssDir)
61
+ .filter(f => f.endsWith('-full.css'))
62
+ .forEach(f => fs.unlinkSync(path.join(cssDir, f)))
63
+ }
64
+ })
65
+
66
+ // Preact is a dependency of this package — all ESM builds externalize it so the
67
+ // consumer's bundler deduplicates to a single shared instance across core and
68
+ // plugins. react/jsx-runtime etc. are not in this list because they are
69
+ // rewritten by the alias plugin before Rollup's external check fires.
70
+ const PREACT_EXTERNALS = [
71
+ 'preact',
72
+ 'preact/compat',
73
+ 'preact/compat/client',
74
+ 'preact/hooks',
75
+ 'preact/jsx-runtime'
76
+ ]
77
+
78
+ // @babel/runtime helpers are externalised so Rollup never inlines or
79
+ // deduplicates them across chunks. Without this, shared helpers (classCallCheck,
80
+ // objectSpread2, etc.) end up in the lazy im-core chunk, forcing a static import
81
+ // from index.js and defeating lazy loading. @babel/runtime is a regular
82
+ // dependency so it auto-installs for consumers and is resolved transparently.
83
+ const BABEL_RUNTIME_EXTERNAL = /@babel\/runtime/
84
+
85
+ const createESMConfig = (entryPath, outDir, isCore = false, manualChunks = null) => {
86
+ const esmDir = path.resolve(__dirname, outDir)
87
+ // Use the parent dir as output.dir so CSS can be emitted to css/index.css
88
+ // (a sibling subdir) without Rollup 4's ban on ".." in emitted file names.
89
+ const rootDir = path.resolve(esmDir, '..')
90
+ const cssDir = path.resolve(rootDir, 'css')
91
+
92
+ // Core build also cleans the shared dist/css before rebuilding
93
+ const dirsToClean = isCore
94
+ ? [path.resolve(__dirname, 'dist/css'), esmDir]
95
+ : [esmDir]
96
+
97
+ return {
98
+ input: entryPath,
99
+
100
+ // react/* is intentionally absent — the alias plugin rewrites those imports
101
+ // to preact/* before Rollup's external check, so only the preact IDs appear.
102
+ external: isCore
103
+ ? [...PREACT_EXTERNALS, BABEL_RUNTIME_EXTERNAL]
104
+ : [
105
+ ...PREACT_EXTERNALS,
106
+ BABEL_RUNTIME_EXTERNAL,
107
+ // maplibre-gl is externalised so ESM consumers get a single shared
108
+ // instance from their own node_modules rather than a 1 MB copy bundled
109
+ // into the provider. (UMD keeps it bundled — no bundler available there.)
110
+ 'maplibre-gl',
111
+ /^@arcgis\/core/
112
+ ],
113
+
114
+ plugins: [
115
+ cleanPlugin(dirsToClean),
116
+
117
+ replace({
118
+ 'process.env.NODE_ENV': JSON.stringify('production'),
119
+ preventAssignment: true
120
+ }),
121
+
122
+ // All builds alias react imports to preact equivalents. Preact is a
123
+ // listed external so after aliasing, Rollup marks the import as external
124
+ // rather than bundling it — giving one shared preact instance per consumer
125
+ // build rather than a separate copy per plugin chunk.
126
+ alias({
127
+ entries: [
128
+ { find: 'react', replacement: 'preact/compat' },
129
+ { find: 'react-dom/client', replacement: 'preact/compat/client' },
130
+ { find: 'react-dom', replacement: 'preact/compat' },
131
+ { find: 'react/jsx-runtime', replacement: 'preact/jsx-runtime' }
132
+ ]
133
+ }),
134
+
135
+ nodeResolve({
136
+ extensions: ['.js', '.jsx'],
137
+ // Force these packages to resolve from root node_modules only,
138
+ // preventing nested copies inside geojson-rbush and mapbox-gl-snap
139
+ // from being bundled separately (saves ~200 KB in draw-ml).
140
+ dedupe: ['@turf/meta', '@turf/helpers', 'robust-predicates']
141
+ }),
142
+ commonjs({ include: /node_modules/ }),
143
+
144
+ babel({
145
+ // 'runtime' mode imports helpers from @babel/runtime rather than
146
+ // inlining them. This prevents Rollup from deduplicating helpers across
147
+ // chunks (which caused static imports between entry and lazy chunks).
148
+ babelHelpers: 'runtime',
149
+ exclude: /node_modules/,
150
+ extensions: ['.js', '.jsx'],
151
+ plugins: ['@babel/plugin-transform-runtime'],
152
+ // Override babel.config.json targets for ESM: target browsers that
153
+ // natively support ES modules (Chrome 61+, Firefox 60+, Safari 10.1+).
154
+ // The UMD build targets old browsers; the ESM build ships modern syntax
155
+ // and lets the consumer's bundler handle their own browser targets.
156
+ // This avoids transpiling classes, arrow functions, async/await etc.
157
+ // into verbose ES5 — the single biggest driver of ESM bundle size.
158
+ presets: [
159
+ ['@babel/preset-env', { targets: { esmodules: true } }],
160
+ ['@babel/preset-react', { runtime: 'automatic' }]
161
+ ]
162
+ }),
163
+
164
+ // extract is an absolute path; Rollup resolves it relative to output.dir
165
+ // (rootDir) → "css/index.css" — no ".." in the emitted fileName.
166
+ postcss({
167
+ extract: path.resolve(cssDir, 'index.css'),
168
+ use: ['sass']
169
+ }),
170
+
171
+ terser(),
172
+
173
+ // webpackChunkNamesPlugin must come after terser so comments survive
174
+ webpackChunkNamesPlugin(),
175
+
176
+ ...(isCore ? [removeFullCssPlugin(cssDir)] : []),
177
+
178
+ // Only runs when ANALYZE=1 is set; writes stats to dist/stats/<name>.html
179
+ ...(process.env.ANALYZE ? [visualizer({
180
+ filename: path.resolve(__dirname, 'dist/stats', `${outDir.replace(/\//g, '-')}.html`),
181
+ open: false,
182
+ gzipSize: true
183
+ })] : [])
184
+ ],
185
+
186
+ output: {
187
+ dir: rootDir,
188
+ format: 'es',
189
+ // JS files go into the esm/ subdirectory within rootDir
190
+ entryFileNames: 'esm/index.js',
191
+ // Core: give auto-generated chunks meaningful names.
192
+ // - initialiseApp → im-core.js (the lazy Preact app chunk)
193
+ // - anything else → im-shell.js (the sync InteractiveMap + shared utils chunk)
194
+ chunkFileNames: isCore
195
+ ? (chunk) => chunk.name === 'initialiseApp' ? 'esm/im-core.js' : 'esm/im-shell.js'
196
+ : 'esm/[name].js',
197
+ // Rollup ignores webpack magic comments; manualChunks is how we assign
198
+ // meaningful names to lazy-loaded splits.
199
+ // Core: no manualChunks — Rollup's natural algorithm keeps shared source
200
+ // modules in the entry chunk, so the lazy initialiseApp split has no static
201
+ // back-imports into index.js. The chunk gets a name via chunkFileNames.
202
+ manualChunks: isCore
203
+ ? undefined
204
+ : (manualChunks || undefined)
205
+ }
206
+ }
207
+ }
208
+
209
+ // === All builds ===
210
+ const ALL_BUILDS = [
211
+ // Core
212
+ { entryPath: './src/index.js', outDir: 'dist/esm', isCore: true },
213
+
214
+ // Providers
215
+ {
216
+ entryPath: './providers/maplibre/src/index.js',
217
+ outDir: 'providers/maplibre/dist/esm',
218
+ // maplibre-gl is external; only the provider class itself becomes a chunk
219
+ manualChunks: (id) => { if (id.includes('/maplibreProvider')) return 'im-maplibre-provider' }
220
+ },
221
+ {
222
+ entryPath: './providers/beta/open-names/src/index.js',
223
+ outDir: 'providers/beta/open-names/dist/esm',
224
+ manualChunks: (id) => { if (id.includes('/reverseGeocode')) return 'im-reverse-geocode' }
225
+ },
226
+ {
227
+ entryPath: './providers/beta/esri/src/index.js',
228
+ outDir: 'providers/beta/esri/dist/esm',
229
+ manualChunks: (id) => { if (id.includes('/esriProvider')) return 'im-esri-provider' }
230
+ },
231
+
232
+ // Plugins — each lazy-loads ./manifest.js; manualChunks names that split chunk
233
+ {
234
+ entryPath: './plugins/beta/scale-bar/src/index.js',
235
+ outDir: 'plugins/beta/scale-bar/dist/esm',
236
+ manualChunks: (id) => { if (id.includes('/manifest')) return 'im-scale-bar-plugin' }
237
+ },
238
+ {
239
+ entryPath: './plugins/beta/use-location/src/index.js',
240
+ outDir: 'plugins/beta/use-location/dist/esm',
241
+ manualChunks: (id) => { if (id.includes('/manifest')) return 'im-use-location-plugin' }
242
+ },
243
+ {
244
+ entryPath: './plugins/search/src/index.js',
245
+ outDir: 'plugins/search/dist/esm',
246
+ manualChunks: (id) => { if (id.includes('/manifest')) return 'im-search-plugin' }
247
+ },
248
+ {
249
+ entryPath: './plugins/interact/src/index.js',
250
+ outDir: 'plugins/interact/dist/esm',
251
+ manualChunks: (id) => { if (id.includes('/manifest')) return 'im-interact-plugin' }
252
+ },
253
+ {
254
+ entryPath: './plugins/beta/datasets/src/index.js',
255
+ outDir: 'plugins/beta/datasets/dist/esm',
256
+ manualChunks: (id) => { if (id.includes('/manifest')) return 'im-datasets-plugin' }
257
+ },
258
+ {
259
+ entryPath: './plugins/beta/map-styles/src/index.js',
260
+ outDir: 'plugins/beta/map-styles/dist/esm',
261
+ manualChunks: (id) => { if (id.includes('/manifest')) return 'im-map-styles-plugin' }
262
+ },
263
+ {
264
+ entryPath: './plugins/beta/draw-ml/src/index.js',
265
+ outDir: 'plugins/beta/draw-ml/dist/esm',
266
+ manualChunks: (id) => { if (id.includes('/manifest')) return 'im-draw-ml-plugin' }
267
+ },
268
+ {
269
+ entryPath: './plugins/beta/draw-es/src/index.js',
270
+ outDir: 'plugins/beta/draw-es/dist/esm',
271
+ manualChunks: (id) => { if (id.includes('/manifest')) return 'im-draw-es-plugin' }
272
+ },
273
+ {
274
+ entryPath: './plugins/beta/frame/src/index.js',
275
+ outDir: 'plugins/beta/frame/dist/esm',
276
+ manualChunks: (id) => { if (id.includes('/manifest')) return 'im-frame-plugin' }
277
+ }
278
+ ]
279
+
280
+ // === Filter via environment variable ===
281
+ const BUILD_TARGET = process.env.BUILD_TARGET // e.g., 'scale-bar' or 'dist/esm' (core)
282
+ const buildsToRun = BUILD_TARGET
283
+ ? ALL_BUILDS.filter(b => b.outDir.includes(BUILD_TARGET))
284
+ : ALL_BUILDS
285
+
286
+ export default buildsToRun.map(b =>
287
+ createESMConfig(b.entryPath, b.outDir, b.isCore || false, b.manualChunks || null)
288
+ )
@@ -66,7 +66,7 @@ const setHybridFullscreen = (state, payload) => {
66
66
  const setBreakpoint = (state, payload) => {
67
67
  const { behaviour, hybridWidth, maxMobileWidth } = payload
68
68
  const panelIds = Object.keys(state.openPanels)
69
- const lastPanelId = panelIds.at(-1)
69
+ const lastPanelId = panelIds[panelIds.length - 1]
70
70
 
71
71
  // For hybrid, isFullscreen is controlled by media query via SET_HYBRID_FULLSCREEN
72
72
  // For other behaviours, calculate it here
@@ -9,8 +9,6 @@
9
9
  */
10
10
 
11
11
  import '../scss/main.scss'
12
- // Polyfills to ensure entry point works on all devices
13
- import './polyfills.js'
14
12
  import historyManager from './historyManager.js'
15
13
  import { parseDataProperties } from './parseDataProperties.js'
16
14
  import { checkDeviceSupport } from './deviceChecker.js'
@@ -26,6 +24,9 @@ import { EVENTS as events } from '../config/events.js'
26
24
  import { createEventBus } from '../services/eventBus.js'
27
25
  import { toggleInertElements } from '../utils/toggleInertElements.js'
28
26
 
27
+ // Polyfills to ensure entry point works on all devices
28
+ import './polyfills.js'
29
+
29
30
  /**
30
31
  * Main entry point for the Interactive Map component.
31
32
  * Handles initialization, lifecycle, and public API methods.
package/webpack.dev.mjs CHANGED
@@ -24,7 +24,14 @@ export default {
24
24
  clean: true,
25
25
  },
26
26
  resolve: {
27
- extensions: ['.tsx', '.ts', '.jsx', '.js']
27
+ extensions: ['.tsx', '.ts', '.jsx', '.js'],
28
+ alias: {
29
+ // Force these to resolve from root node_modules, preventing nested copies
30
+ // inside geojson-rbush and mapbox-gl-snap from being bundled separately.
31
+ '@turf/meta': path.resolve(__dirname, 'node_modules/@turf/meta'),
32
+ '@turf/helpers': path.resolve(__dirname, 'node_modules/@turf/helpers'),
33
+ 'robust-predicates': path.resolve(__dirname, 'node_modules/robust-predicates')
34
+ }
28
35
  },
29
36
  plugins: [
30
37
  new MiniCssExtractPlugin({
@@ -106,6 +113,7 @@ export default {
106
113
  setupMiddlewares
107
114
  },
108
115
  optimization: {
116
+ chunkIds: 'named',
109
117
  splitChunks: {
110
118
  chunks () {
111
119
  return false
package/webpack.prod.mjs CHANGED
@@ -2,6 +2,8 @@ import { merge } from 'webpack-merge'
2
2
  import common from './webpack.dev.mjs'
3
3
  import CompressionPlugin from 'compression-webpack-plugin'
4
4
  import zlib from 'zlib'
5
+ import path, { dirname } from 'path'
6
+ import { fileURLToPath } from 'url'
5
7
 
6
8
  export default merge(common, {
7
9
  mode: 'production',
@@ -28,7 +30,12 @@ export default merge(common, {
28
30
  react: 'preact/compat',
29
31
  'react-dom/test-utils': 'preact/test-utils',
30
32
  'react-dom': 'preact/compat',
31
- 'react/jsx-runtime': 'preact/jsx-runtime'
33
+ 'react/jsx-runtime': 'preact/jsx-runtime',
34
+ // Force these to resolve from root node_modules, preventing nested copies
35
+ // inside geojson-rbush and mapbox-gl-snap from being bundled separately.
36
+ '@turf/meta': path.resolve(dirname(fileURLToPath(import.meta.url)), 'node_modules/@turf/meta'),
37
+ '@turf/helpers': path.resolve(dirname(fileURLToPath(import.meta.url)), 'node_modules/@turf/helpers'),
38
+ 'robust-predicates': path.resolve(dirname(fileURLToPath(import.meta.url)), 'node_modules/robust-predicates')
32
39
  }
33
40
  },
34
41
  performance: {
package/webpack.umd.mjs CHANGED
@@ -111,7 +111,6 @@ const createUMDConfig = (entryName, entryPath, libraryPath, outDir, isCore = fal
111
111
  module: {
112
112
  rules: [
113
113
  { test: /\.jsx?$/, loader: 'babel-loader', exclude: /node_modules/ },
114
- { test: /\.tsx?$/, loader: 'ts-loader', exclude: /node_modules/ },
115
114
  { test: /\.css$/i, use: [MiniCssExtractPlugin.loader, 'css-loader'] },
116
115
  { test: /\.s[ac]ss$/i, use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'] }
117
116
  ]
@@ -137,7 +136,7 @@ const ALL_BUILDS = [
137
136
 
138
137
  // Plugins
139
138
  { entryPath: './plugins/beta/scale-bar/src/index.js', libraryPath: 'scaleBarPlugin', outDir: 'plugins/beta/scale-bar/dist/umd' },
140
- { entryPath: './plugins/beta/use-location/src/index.js', libraryPath: 'drawPolygonMLPlugin', outDir: 'plugins/beta/use-location/dist/umd' },
139
+ { entryPath: './plugins/beta/use-location/src/index.js', libraryPath: 'useLocationPlugin', outDir: 'plugins/beta/use-location/dist/umd' },
141
140
  { entryPath: './plugins/search/src/index.js', libraryPath: 'searchPlugin', outDir: 'plugins/search/dist/umd' },
142
141
  { entryPath: './plugins/interact/src/index.js', libraryPath: 'interactPlugin', outDir: 'plugins/interact/dist/umd' },
143
142
  { entryPath: './plugins/beta/datasets/src/index.js', libraryPath: 'datasetsPlugin', outDir: 'plugins/beta/datasets/dist/umd' },
@@ -1 +0,0 @@
1
- /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */
@@ -1 +0,0 @@
1
- /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */
@@ -1 +0,0 @@
1
- /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */
@@ -1 +0,0 @@
1
- /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */
@@ -1 +0,0 @@
1
- /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */
@@ -1 +0,0 @@
1
- /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */
@@ -1 +0,0 @@
1
- /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */
@@ -1 +0,0 @@
1
- /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */
@@ -1 +0,0 @@
1
- /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */
@@ -1 +0,0 @@
1
- /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */
@@ -1 +0,0 @@
1
- /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */
@@ -1 +0,0 @@
1
- /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */
@@ -1,6 +0,0 @@
1
- /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */
2
-
3
- /**
4
- * MapLibre GL JS
5
- * @license 3-Clause BSD. Full text of license: https://github.com/maplibre/maplibre-gl-js/blob/v5.17.0/LICENSE.txt
6
- */