@defra/interactive-map 0.0.3-alpha → 0.0.4-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/README.md +16 -57
- package/dist/esm/im-core.js +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/umd/im-core.js +1 -1
- package/dist/umd/index.js +1 -1
- package/docs/api/button-definition.md +176 -0
- package/docs/api/context.md +124 -0
- package/docs/api/control-definition.md +72 -0
- package/docs/api/icon-definition.md +28 -0
- package/docs/api/map-style-config.md +76 -0
- package/docs/api/marker-config.md +51 -0
- package/docs/api/panel-definition.md +117 -0
- package/docs/api/slots.md +25 -0
- package/docs/api.md +713 -0
- package/docs/architecture.md +139 -0
- package/docs/building-a-plugin.md +149 -0
- package/docs/getting-started.md +46 -0
- package/docs/govuk-prototype.md +0 -0
- package/docs/plugins/interact.md +205 -0
- package/docs/plugins/map-styles.md +84 -0
- package/docs/plugins/plugin-context.md +67 -0
- package/docs/plugins/plugin-descriptor.md +71 -0
- package/docs/plugins/plugin-manifest.md +118 -0
- package/docs/plugins/scale-bar.md +62 -0
- package/docs/plugins/search.md +162 -0
- package/docs/plugins.md +116 -0
- package/govuk-prototype-kit.config.json +7 -7
- package/package.json +14 -1
- package/plugins/beta/datasets/dist/esm/im-datasets-plugin.js +1 -0
- package/plugins/beta/datasets/dist/esm/index.js +2 -0
- package/plugins/beta/datasets/dist/umd/im-datasets-plugin.js +1 -0
- package/plugins/beta/datasets/dist/umd/index.js +2 -0
- package/plugins/{datasets → beta/datasets}/src/manifest.js +1 -1
- package/plugins/{datasets → beta/datasets}/src/mapLayers.js +1 -1
- package/plugins/{datasets → beta/datasets}/src/panels/Key.jsx +1 -1
- package/plugins/beta/draw-ml/dist/esm/im-draw-ml-plugin.js +1 -0
- package/plugins/beta/draw-ml/dist/esm/index.js +2 -0
- package/plugins/beta/draw-ml/dist/umd/im-draw-ml-plugin.js +1 -0
- package/plugins/beta/draw-ml/dist/umd/index.js +2 -0
- package/plugins/{draw-ml → beta/draw-ml}/src/api/editFeature.js +1 -1
- package/plugins/beta/draw-ml/src/api/merge.js +9 -0
- package/plugins/beta/draw-ml/src/api/newLine.js +43 -0
- package/plugins/{draw-ml → beta/draw-ml}/src/api/newPolygon.js +5 -5
- package/plugins/beta/draw-ml/src/api/split.js +81 -0
- package/plugins/{draw-ml → beta/draw-ml}/src/defaults.js +2 -0
- package/plugins/{draw-ml → beta/draw-ml}/src/events.js +105 -3
- package/plugins/{draw-ml → beta/draw-ml}/src/manifest.js +17 -11
- package/plugins/{draw-ml → beta/draw-ml}/src/mapboxDraw.js +51 -2
- package/plugins/{draw-ml → beta/draw-ml}/src/mapboxSnap.js +2 -0
- package/plugins/beta/draw-ml/src/modes/createDrawMode.js +496 -0
- package/plugins/beta/draw-ml/src/modes/drawLineMode.js +18 -0
- package/plugins/beta/draw-ml/src/modes/drawPolygonMode.js +16 -0
- package/plugins/beta/draw-ml/src/modes/editVertexMode.js +792 -0
- package/plugins/{draw-ml → beta/draw-ml}/src/reducer.js +30 -2
- package/plugins/{draw-ml → beta/draw-ml}/src/styles.js +66 -36
- package/plugins/beta/draw-ml/src/undoStack.js +50 -0
- package/plugins/beta/draw-ml/src/utils/debounce.js +16 -0
- package/plugins/beta/draw-ml/src/utils/spatial.js +258 -0
- package/plugins/beta/frame/dist/esm/im-frame-plugin.js +1 -0
- package/plugins/beta/frame/dist/esm/index.js +2 -0
- package/plugins/beta/frame/dist/umd/im-frame-plugin.js +1 -0
- package/plugins/beta/frame/dist/umd/index.js +2 -0
- package/plugins/beta/map-styles/dist/esm/im-map-styles-plugin.js +1 -0
- package/plugins/beta/map-styles/dist/esm/index.js +2 -0
- package/plugins/beta/map-styles/dist/umd/im-map-styles-plugin.js +1 -0
- package/plugins/beta/map-styles/dist/umd/index.js +2 -0
- package/plugins/{map-styles → beta/map-styles}/src/MapStyles.jsx +1 -1
- package/plugins/{map-styles → beta/map-styles}/src/manifest.js +8 -10
- package/plugins/beta/scale-bar/dist/esm/im-scale-bar-plugin.js +1 -0
- package/plugins/beta/scale-bar/dist/esm/index.js +2 -0
- package/plugins/beta/scale-bar/dist/umd/im-scale-bar-plugin.js +1 -0
- package/plugins/beta/scale-bar/dist/umd/index.js +2 -0
- package/plugins/beta/use-location/dist/esm/im-use-location-plugin.js +1 -0
- package/plugins/beta/use-location/dist/esm/index.js +2 -0
- package/plugins/beta/use-location/dist/umd/im-use-location-plugin.js +1 -0
- package/plugins/beta/use-location/dist/umd/index.js +2 -0
- package/plugins/interact/dist/esm/im-interact-plugin.js +1 -1
- package/plugins/interact/dist/esm/index.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.test.js +97 -0
- package/plugins/interact/src/api/clear.test.js +18 -0
- package/plugins/interact/src/api/disable.test.js +12 -0
- package/plugins/interact/src/api/enable.test.js +48 -0
- package/plugins/interact/src/api/selectFeature.test.js +33 -0
- package/plugins/interact/src/api/unselectFeature.test.js +33 -0
- package/plugins/interact/src/defaults.js +1 -0
- package/plugins/interact/src/events.test.js +151 -0
- package/plugins/interact/src/hooks/useHighlightSync.test.js +212 -0
- package/plugins/interact/src/hooks/useInteractionHandlers.js +14 -7
- package/plugins/interact/src/hooks/useInteractionHandlers.test.js +260 -0
- package/plugins/interact/src/index.test.js +22 -0
- package/plugins/interact/src/manifest.js +1 -1
- package/plugins/interact/src/manifest.test.js +94 -0
- package/plugins/interact/src/reducer.js +10 -1
- package/plugins/interact/src/reducer.test.js +142 -0
- package/plugins/interact/src/utils/buildStylesMap.test.js +57 -0
- package/plugins/interact/src/utils/featureQueries.test.js +56 -0
- package/plugins/interact/src/utils/turfHelpers.js +30 -0
- package/plugins/interact/src/utils/turfHelpers.test.js +30 -0
- 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/utils/parseOsNamesResults.js +3 -7
- package/providers/{esri → beta/esri}/src/mapEvents.js +2 -2
- package/providers/beta/open-names/dist/esm/im-reverse-geocode.js +2 -0
- package/providers/beta/open-names/dist/esm/index.js +2 -0
- package/providers/beta/open-names/dist/umd/im-reverse-geocode.js +2 -0
- package/providers/beta/open-names/dist/umd/index.js +2 -0
- package/providers/maplibre/dist/esm/im-maplibre-framework.js +1 -1
- package/providers/maplibre/dist/esm/im-maplibre-framework.js.LICENSE.txt +1 -1
- package/providers/maplibre/dist/esm/im-maplibre-legacy-framework.js +1 -1
- package/providers/maplibre/dist/esm/im-maplibre-provider.js +1 -1
- package/providers/maplibre/dist/esm/index.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-legacy-framework.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/index.js +14 -1
- package/providers/maplibre/src/maplibreProvider.js +127 -0
- package/sonar-project.properties +1 -1
- package/src/App/hooks/useInterfaceAPI.js +24 -1
- package/src/App/renderer/mapButtons.js +1 -1
- package/src/App/store/appActionsMap.js +22 -1
- package/src/InteractiveMap/InteractiveMap.js +114 -6
- package/src/config/defaults.js +29 -20
- package/src/config/events.js +110 -4
- package/src/index.js +5 -2
- package/src/scss/tools/_border-focus.scss +20 -4
- package/src/types.js +585 -0
- package/webpack.esm.mjs +8 -8
- package/webpack.umd.mjs +8 -8
- package/plugins/datasets/dist/esm/im-datasets-plugin.js +0 -1
- package/plugins/datasets/dist/esm/index.js +0 -2
- package/plugins/datasets/dist/umd/im-datasets-plugin.js +0 -1
- package/plugins/datasets/dist/umd/index.js +0 -2
- package/plugins/draw-ml/dist/esm/im-draw-ml-plugin.js +0 -1
- package/plugins/draw-ml/dist/esm/index.js +0 -2
- package/plugins/draw-ml/dist/umd/im-draw-ml-plugin.js +0 -1
- package/plugins/draw-ml/dist/umd/index.js +0 -2
- package/plugins/draw-ml/src/modes/drawVertexMode.js +0 -275
- package/plugins/draw-ml/src/modes/editVertexMode.js +0 -426
- package/plugins/draw-ml/src/utils.js +0 -102
- package/plugins/frame/dist/esm/im-frame-plugin.js +0 -1
- package/plugins/frame/dist/esm/index.js +0 -2
- package/plugins/frame/dist/umd/im-frame-plugin.js +0 -1
- package/plugins/frame/dist/umd/index.js +0 -2
- package/plugins/map-styles/dist/esm/im-map-styles-plugin.js +0 -1
- package/plugins/map-styles/dist/esm/index.js +0 -2
- package/plugins/map-styles/dist/umd/im-map-styles-plugin.js +0 -1
- package/plugins/map-styles/dist/umd/index.js +0 -2
- package/plugins/scale-bar/dist/esm/im-scale-bar-plugin.js +0 -1
- package/plugins/scale-bar/dist/esm/index.js +0 -2
- package/plugins/scale-bar/dist/umd/im-scale-bar-plugin.js +0 -1
- package/plugins/scale-bar/dist/umd/index.js +0 -2
- package/plugins/use-location/dist/esm/im-use-location-plugin.js +0 -1
- package/plugins/use-location/dist/esm/index.js +0 -2
- package/plugins/use-location/dist/umd/im-use-location-plugin.js +0 -1
- package/plugins/use-location/dist/umd/index.js +0 -2
- package/providers/open-names/dist/esm/im-reverse-geocode.js +0 -2
- package/providers/open-names/dist/esm/index.js +0 -2
- package/providers/open-names/dist/umd/im-reverse-geocode.js +0 -2
- package/providers/open-names/dist/umd/index.js +0 -2
- /package/docs/architecture/{ARCHITECTURE_DIAGRAMS.md → architecture-diagrams.md} +0 -0
- /package/plugins/{datasets → beta/datasets}/dist/css/index.css +0 -0
- /package/plugins/{datasets → beta/datasets}/dist/esm/index.js.LICENSE.txt +0 -0
- /package/plugins/{datasets → beta/datasets}/dist/umd/index.js.LICENSE.txt +0 -0
- /package/plugins/{datasets → beta/datasets}/src/DatasetsInit.jsx +0 -0
- /package/plugins/{datasets → beta/datasets}/src/api/addDataset.js +0 -0
- /package/plugins/{datasets → beta/datasets}/src/api/hideDataset.js +0 -0
- /package/plugins/{datasets → beta/datasets}/src/api/hideFeatures.js +0 -0
- /package/plugins/{datasets → beta/datasets}/src/api/removeDataset.js +0 -0
- /package/plugins/{datasets → beta/datasets}/src/api/showDataset.js +0 -0
- /package/plugins/{datasets → beta/datasets}/src/api/showFeatures.js +0 -0
- /package/plugins/{datasets → beta/datasets}/src/datasets.js +0 -0
- /package/plugins/{datasets → beta/datasets}/src/datasets.scss +0 -0
- /package/plugins/{datasets → beta/datasets}/src/defaults.js +0 -0
- /package/plugins/{datasets → beta/datasets}/src/handleSetMapStyle.js +0 -0
- /package/plugins/{datasets → beta/datasets}/src/index.js +0 -0
- /package/plugins/{datasets → beta/datasets}/src/panels/Key.module.scss +0 -0
- /package/plugins/{datasets → beta/datasets}/src/panels/Layers.jsx +0 -0
- /package/plugins/{datasets → beta/datasets}/src/panels/Layers.module.scss +0 -0
- /package/plugins/{datasets → beta/datasets}/src/reducer.js +0 -0
- /package/plugins/{datasets → beta/datasets}/src/utils/bbox.js +0 -0
- /package/plugins/{datasets → beta/datasets}/src/utils/debounce.js +0 -0
- /package/plugins/{datasets → beta/datasets}/src/utils/filters.js +0 -0
- /package/plugins/{draw-es → beta/draw-es}/src/DrawInit.jsx +0 -0
- /package/plugins/{draw-es → beta/draw-es}/src/api/addFeature.js +0 -0
- /package/plugins/{draw-es → beta/draw-es}/src/api/deleteFeature.js +0 -0
- /package/plugins/{draw-es → beta/draw-es}/src/api/editFeature.js +0 -0
- /package/plugins/{draw-es → beta/draw-es}/src/api/newPolygon.js +0 -0
- /package/plugins/{draw-es → beta/draw-es}/src/events.js +0 -0
- /package/plugins/{draw-es → beta/draw-es}/src/graphic.js +0 -0
- /package/plugins/{draw-es → beta/draw-es}/src/index.js +0 -0
- /package/plugins/{draw-es → beta/draw-es}/src/manifest.js +0 -0
- /package/plugins/{draw-es → beta/draw-es}/src/reducer.js +0 -0
- /package/plugins/{draw-es → beta/draw-es}/src/sketchViewModel.js +0 -0
- /package/plugins/{draw-ml → beta/draw-ml}/dist/css/index.css +0 -0
- /package/plugins/{draw-ml → beta/draw-ml}/dist/esm/index.js.LICENSE.txt +0 -0
- /package/plugins/{draw-ml → beta/draw-ml}/dist/umd/index.js.LICENSE.txt +0 -0
- /package/plugins/{draw-ml → beta/draw-ml}/src/DrawInit.jsx +0 -0
- /package/plugins/{draw-ml → beta/draw-ml}/src/api/addFeature.js +0 -0
- /package/plugins/{draw-ml → beta/draw-ml}/src/api/deleteFeature.js +0 -0
- /package/plugins/{draw-ml → beta/draw-ml}/src/draw.scss +0 -0
- /package/plugins/{draw-ml → beta/draw-ml}/src/index.js +0 -0
- /package/plugins/{draw-ml → beta/draw-ml}/src/modes/disabledMode.js +0 -0
- /package/plugins/{draw-ml/src → beta/draw-ml/src/utils}/snapHelpers.js +0 -0
- /package/plugins/{frame → beta/frame}/dist/css/index.css +0 -0
- /package/plugins/{frame → beta/frame}/dist/esm/index.js.LICENSE.txt +0 -0
- /package/plugins/{frame → beta/frame}/dist/umd/index.js.LICENSE.txt +0 -0
- /package/plugins/{frame → beta/frame}/package.json +0 -0
- /package/plugins/{frame → beta/frame}/src/Frame.jsx +0 -0
- /package/plugins/{frame → beta/frame}/src/FrameInit.jsx +0 -0
- /package/plugins/{frame → beta/frame}/src/api/addFrame.js +0 -0
- /package/plugins/{frame → beta/frame}/src/api/editFeature.js +0 -0
- /package/plugins/{frame → beta/frame}/src/config.js +0 -0
- /package/plugins/{frame → beta/frame}/src/frame.scss +0 -0
- /package/plugins/{frame → beta/frame}/src/index.js +0 -0
- /package/plugins/{frame → beta/frame}/src/manifest.js +0 -0
- /package/plugins/{frame → beta/frame}/src/reducer.js +0 -0
- /package/plugins/{frame → beta/frame}/src/utils.js +0 -0
- /package/plugins/{map-styles → beta/map-styles}/dist/css/index.css +0 -0
- /package/plugins/{map-styles → beta/map-styles}/dist/esm/index.js.LICENSE.txt +0 -0
- /package/plugins/{map-styles → beta/map-styles}/dist/umd/index.js.LICENSE.txt +0 -0
- /package/plugins/{map-styles → beta/map-styles}/src/MapStylesInit.jsx +0 -0
- /package/plugins/{map-styles → beta/map-styles}/src/config.js +0 -0
- /package/plugins/{map-styles → beta/map-styles}/src/index.js +0 -0
- /package/plugins/{map-styles → beta/map-styles}/src/mapStyles.scss +0 -0
- /package/plugins/{scale-bar → beta/scale-bar}/dist/css/index.css +0 -0
- /package/plugins/{scale-bar → beta/scale-bar}/dist/esm/index.js.LICENSE.txt +0 -0
- /package/plugins/{scale-bar → beta/scale-bar}/dist/umd/index.js.LICENSE.txt +0 -0
- /package/plugins/{scale-bar → beta/scale-bar}/package.json +0 -0
- /package/plugins/{scale-bar → beta/scale-bar}/src/ScaleBar.jsx +0 -0
- /package/plugins/{scale-bar → beta/scale-bar}/src/ScaleBar.test.jsx +0 -0
- /package/plugins/{scale-bar → beta/scale-bar}/src/index.js +0 -0
- /package/plugins/{scale-bar → beta/scale-bar}/src/index.test.js +0 -0
- /package/plugins/{scale-bar → beta/scale-bar}/src/manifest.js +0 -0
- /package/plugins/{scale-bar → beta/scale-bar}/src/scaleBar.scss +0 -0
- /package/plugins/{scale-bar → beta/scale-bar}/src/utils.js +0 -0
- /package/plugins/{scale-bar → beta/scale-bar}/src/utils.test.js +0 -0
- /package/plugins/{use-location → beta/use-location}/dist/esm/index.js.LICENSE.txt +0 -0
- /package/plugins/{use-location → beta/use-location}/dist/umd/index.js.LICENSE.txt +0 -0
- /package/plugins/{use-location → beta/use-location}/src/UseLocation.jsx +0 -0
- /package/plugins/{use-location → beta/use-location}/src/UseLocationInit.jsx +0 -0
- /package/plugins/{use-location → beta/use-location}/src/defaults.js +0 -0
- /package/plugins/{use-location → beta/use-location}/src/events.js +0 -0
- /package/plugins/{use-location → beta/use-location}/src/index.js +0 -0
- /package/plugins/{use-location → beta/use-location}/src/manifest.js +0 -0
- /package/plugins/{use-location → beta/use-location}/src/reducer.js +0 -0
- /package/providers/{esri → beta/esri}/src/appEvents.js +0 -0
- /package/providers/{esri → beta/esri}/src/defaults.js +0 -0
- /package/providers/{esri → beta/esri}/src/esriProvider.js +0 -0
- /package/providers/{esri → beta/esri}/src/esriProvider.scss +0 -0
- /package/providers/{esri → beta/esri}/src/index.js +0 -0
- /package/providers/{esri → beta/esri}/src/utils/coords.js +0 -0
- /package/providers/{esri → beta/esri}/src/utils/detectWebGL.js +0 -0
- /package/providers/{esri → beta/esri}/src/utils/esriFixes.js +0 -0
- /package/providers/{esri → beta/esri}/src/utils/query.js +0 -0
- /package/providers/{esri → beta/esri}/src/utils/spatial.js +0 -0
- /package/providers/{open-names → beta/open-names}/dist/esm/im-reverse-geocode.js.LICENSE.txt +0 -0
- /package/providers/{open-names → beta/open-names}/dist/esm/index.js.LICENSE.txt +0 -0
- /package/providers/{open-names → beta/open-names}/dist/umd/im-reverse-geocode.js.LICENSE.txt +0 -0
- /package/providers/{open-names → beta/open-names}/dist/umd/index.js.LICENSE.txt +0 -0
- /package/providers/{open-names → beta/open-names}/src/index.js +0 -0
- /package/providers/{open-names → beta/open-names}/src/reverseGeocode.js +0 -0
- /package/providers/{open-names → beta/open-names}/src/utils/mapToLocationModel.js +0 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Programmatically merge multiple polygons ia single polygon
|
|
3
|
+
* @param {object} context - plugin context
|
|
4
|
+
* @param {string} polygon[] - an a rray of polygons to merge
|
|
5
|
+
*/
|
|
6
|
+
export const merge = ({ services }, polygons) => {
|
|
7
|
+
console.log('merge')
|
|
8
|
+
console.log(polygons)
|
|
9
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { getSnapInstance } from '../utils/snapHelpers.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Programmatically create a new line
|
|
5
|
+
* @param {object} context - plugin context
|
|
6
|
+
* @param {string} featureId - ID for the new feature
|
|
7
|
+
* @param {object} options - Options including snapLayers.
|
|
8
|
+
*/
|
|
9
|
+
export const newLine = ({ appState, appConfig, pluginState, mapProvider }, featureId, options = {}) => {
|
|
10
|
+
const { dispatch } = pluginState
|
|
11
|
+
const { draw, map } = mapProvider
|
|
12
|
+
|
|
13
|
+
if (!draw) {
|
|
14
|
+
return
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Set per-call snap layers if provided
|
|
18
|
+
const snap = getSnapInstance(map)
|
|
19
|
+
if (snap?.setSnapLayers) {
|
|
20
|
+
snap.setSnapLayers(options.snapLayers || null)
|
|
21
|
+
} else if (options.snapLayers) {
|
|
22
|
+
// Snap instance not ready yet - store for later
|
|
23
|
+
map._pendingSnapLayers = options.snapLayers
|
|
24
|
+
} else {
|
|
25
|
+
// No action
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Update state so UI can react to snap layer availability
|
|
29
|
+
dispatch({ type: 'SET_HAS_SNAP_LAYERS', payload: options.snapLayers?.length > 0 })
|
|
30
|
+
|
|
31
|
+
// Change mode to draw_line
|
|
32
|
+
draw.changeMode('draw_line', {
|
|
33
|
+
container: appState.layoutRefs.viewportRef.current,
|
|
34
|
+
vertexMarkerId: `${appConfig.id}-cross-hair`,
|
|
35
|
+
addVertexButtonId: `${appConfig.id}-draw-add-point`,
|
|
36
|
+
interfaceType: appState.interfaceType,
|
|
37
|
+
getSnapEnabled: () => mapProvider.snapEnabled === true,
|
|
38
|
+
featureId
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
// Set mode to draw_line
|
|
42
|
+
dispatch({ type: 'SET_MODE', payload: 'draw_line' })
|
|
43
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getSnapInstance } from '../snapHelpers.js'
|
|
1
|
+
import { getSnapInstance } from '../utils/snapHelpers.js'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Programmatically create a new polygon
|
|
@@ -28,8 +28,8 @@ export const newPolygon = ({ appState, appConfig, pluginState, mapProvider }, fe
|
|
|
28
28
|
// Update state so UI can react to snap layer availability
|
|
29
29
|
dispatch({ type: 'SET_HAS_SNAP_LAYERS', payload: options.snapLayers?.length > 0 })
|
|
30
30
|
|
|
31
|
-
// Change mode to
|
|
32
|
-
draw.changeMode('
|
|
31
|
+
// Change mode to draw_polygon
|
|
32
|
+
draw.changeMode('draw_polygon', {
|
|
33
33
|
container: appState.layoutRefs.viewportRef.current,
|
|
34
34
|
vertexMarkerId: `${appConfig.id}-cross-hair`,
|
|
35
35
|
addVertexButtonId: `${appConfig.id}-draw-add-point`,
|
|
@@ -38,6 +38,6 @@ export const newPolygon = ({ appState, appConfig, pluginState, mapProvider }, fe
|
|
|
38
38
|
featureId
|
|
39
39
|
})
|
|
40
40
|
|
|
41
|
-
// Set mode to
|
|
42
|
-
dispatch({ type: 'SET_MODE', payload: '
|
|
41
|
+
// Set mode to draw_polygon
|
|
42
|
+
dispatch({ type: 'SET_MODE', payload: 'draw_polygon' })
|
|
43
43
|
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { getSnapInstance } from '../utils/snapHelpers.js'
|
|
2
|
+
import { splitPolygon } from '../utils/spatial.js'
|
|
3
|
+
import { debounce } from '../utils/debounce.js'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Programmatically split a polygon or line
|
|
7
|
+
* @param {object} context - plugin context
|
|
8
|
+
* @param {string} feature - the new feature to be split
|
|
9
|
+
* @param {object} options - Options including snapLayers.
|
|
10
|
+
*/
|
|
11
|
+
export const split = ({ appState, appConfig, pluginState, mapProvider }, featureId, options = {}) => {
|
|
12
|
+
const { dispatch } = pluginState
|
|
13
|
+
const { draw, map } = mapProvider
|
|
14
|
+
|
|
15
|
+
if (!draw) {
|
|
16
|
+
return
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Get target polygon feature
|
|
20
|
+
const polygonFeature = draw.get(featureId)
|
|
21
|
+
|
|
22
|
+
// Always include 'stroke-inactive' in snap layers
|
|
23
|
+
const snapLayers = ['stroke-inactive.cold', ...(options.snapLayers || [])]
|
|
24
|
+
|
|
25
|
+
// Set per-call snap layers if provided
|
|
26
|
+
const snap = getSnapInstance(map)
|
|
27
|
+
|
|
28
|
+
if (snap?.setSnapLayers) {
|
|
29
|
+
snap.setSnapLayers(snapLayers)
|
|
30
|
+
} else if (options.snapLayers) {
|
|
31
|
+
// Snap instance not ready yet - store for later
|
|
32
|
+
map._pendingSnapLayers = snapLayers
|
|
33
|
+
} else {
|
|
34
|
+
// No action
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Update state so UI can react to snap layer availability
|
|
38
|
+
dispatch({ type: 'SET_HAS_SNAP_LAYERS', payload: true })
|
|
39
|
+
|
|
40
|
+
// Change mode to draw_line
|
|
41
|
+
draw.changeMode('draw_line', {
|
|
42
|
+
container: appState.layoutRefs.viewportRef.current,
|
|
43
|
+
vertexMarkerId: `${appConfig.id}-cross-hair`,
|
|
44
|
+
addVertexButtonId: `${appConfig.id}-draw-add-point`,
|
|
45
|
+
interfaceType: appState.interfaceType,
|
|
46
|
+
getSnapEnabled: () => mapProvider.snapEnabled === true,
|
|
47
|
+
featureId: '_splitter',
|
|
48
|
+
properties: { splitter: 'invalid' }
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
// Perform split
|
|
52
|
+
map.on('draw.create', (e) => {
|
|
53
|
+
const lineFeature = e.features[0]
|
|
54
|
+
const featureCollection = splitPolygon(polygonFeature, lineFeature)
|
|
55
|
+
draw.setFeatureProperty('_splitter', 'splitter', featureCollection ? 'valid' : 'invalid')
|
|
56
|
+
dispatch({ type: 'SET_ACTION', payload: { name: 'split', isValid: !!featureCollection }})
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
// Real time check for valid line
|
|
60
|
+
const DEBOUNCE_SPLIT_POLYGON = 50
|
|
61
|
+
const onGeometryChange = debounce((e) => {
|
|
62
|
+
if (e.coordinates.length < 2) {
|
|
63
|
+
return
|
|
64
|
+
}
|
|
65
|
+
const lineFeature = { id: '_splitter', geometry: { type: 'LineString', coordinates: e.coordinates }}
|
|
66
|
+
const featureCollection = splitPolygon(polygonFeature, lineFeature)
|
|
67
|
+
const isValid = !!featureCollection
|
|
68
|
+
e.properties.splitter = isValid ? 'valid' : 'invalid'
|
|
69
|
+
e.ctx.store.render()
|
|
70
|
+
if (draw.getMode() === 'edit_vertex') {
|
|
71
|
+
dispatch({ type: 'SET_ACTION', payload: { name: 'split', isValid }})
|
|
72
|
+
}
|
|
73
|
+
}, DEBOUNCE_SPLIT_POLYGON)
|
|
74
|
+
map.on('draw.geometrychange', onGeometryChange)
|
|
75
|
+
|
|
76
|
+
// Set mode to 'draw_line'
|
|
77
|
+
dispatch({ type: 'SET_MODE', payload: 'draw_line' })
|
|
78
|
+
|
|
79
|
+
// Set action to 'split'
|
|
80
|
+
dispatch({ type: 'SET_ACTION', payload: { name: 'split' }})
|
|
81
|
+
}
|
|
@@ -2,6 +2,8 @@ export const DEFAULTS = {
|
|
|
2
2
|
editColorsForeground: { light: 'rgba(29,112,184,1)', dark: '#ffffff' },
|
|
3
3
|
editColorsBackground: { light: '#ffffff', dark: 'rgba(11,12,12,1)' },
|
|
4
4
|
editColorsHalo: { light: 'rgba(11,12,12,1)', dark: '#ffffff' },
|
|
5
|
+
splitInvalidColors: { light: 'rgba(29,112,184,1)', dark: 'rgba(29,112,184,1)' },
|
|
6
|
+
splitValidColors: { light: 'rgba(29,112,184,1)', dark: 'rgba(29,112,184,1)' },
|
|
5
7
|
stroke: 'rgba(212,53,28,1)',
|
|
6
8
|
strokeWidth: 2,
|
|
7
9
|
fill: 'rgba(212,53,28,0.1)',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { clearSnapState, getSnapInstance } from './snapHelpers.js'
|
|
1
|
+
import { clearSnapState, getSnapInstance } from './utils/snapHelpers.js'
|
|
2
2
|
|
|
3
3
|
export function attachEvents ({ appState, appConfig, mapState, pluginState, mapProvider, buttonConfig, eventBus }) {
|
|
4
4
|
const {
|
|
@@ -14,8 +14,24 @@ export function attachEvents ({ appState, appConfig, mapState, pluginState, mapP
|
|
|
14
14
|
const { map, draw } = mapProvider
|
|
15
15
|
const { dispatch, feature, tempFeature } = pluginState
|
|
16
16
|
|
|
17
|
+
// Helper to disable snap and hide indicators
|
|
18
|
+
const disableSnap = () => {
|
|
19
|
+
mapProvider.snapEnabled = false
|
|
20
|
+
dispatch({ type: 'SET_SNAP', payload: false })
|
|
21
|
+
const snap = getSnapInstance(map)
|
|
22
|
+
if (snap) {
|
|
23
|
+
snap.setSnapStatus?.(false)
|
|
24
|
+
clearSnapState(snap)
|
|
25
|
+
}
|
|
26
|
+
if (map.getLayer('snap-helper-circle')) {
|
|
27
|
+
map.setLayoutProperty('snap-helper-circle', 'visibility', 'none')
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
17
31
|
// --- Done
|
|
18
32
|
const handleDone = () => {
|
|
33
|
+
disableSnap()
|
|
34
|
+
mapProvider.undoStack?.clear()
|
|
19
35
|
draw.changeMode('disabled')
|
|
20
36
|
dispatch({ type: 'SET_MODE', payload: null })
|
|
21
37
|
dispatch({ type: 'SET_FEATURE', payload: { feature: null, tempFeature: null }})
|
|
@@ -25,12 +41,16 @@ export function attachEvents ({ appState, appConfig, mapState, pluginState, mapP
|
|
|
25
41
|
|
|
26
42
|
// --- Cancel
|
|
27
43
|
const handleCancel = () => {
|
|
28
|
-
|
|
44
|
+
if (tempFeature?.id) {
|
|
45
|
+
draw.delete(tempFeature.id)
|
|
46
|
+
}
|
|
29
47
|
|
|
30
48
|
// Reinstate initial feature
|
|
31
49
|
if (feature) {
|
|
32
50
|
draw.add(feature)
|
|
33
51
|
}
|
|
52
|
+
disableSnap()
|
|
53
|
+
mapProvider.undoStack?.clear()
|
|
34
54
|
draw.changeMode('disabled')
|
|
35
55
|
|
|
36
56
|
dispatch({ type: 'SET_MODE', payload: null })
|
|
@@ -39,10 +59,67 @@ export function attachEvents ({ appState, appConfig, mapState, pluginState, mapP
|
|
|
39
59
|
}
|
|
40
60
|
drawCancel.onClick = handleCancel
|
|
41
61
|
|
|
62
|
+
// --- Finish shape (programmatically complete the drawing)
|
|
63
|
+
const handleFinish = () => {
|
|
64
|
+
const mode = draw.getMode()
|
|
65
|
+
if (!['draw_polygon', 'draw_line'].includes(mode)) {
|
|
66
|
+
return
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const features = draw.getAll().features
|
|
70
|
+
if (features.length === 0) {
|
|
71
|
+
return
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const feature = features[0]
|
|
75
|
+
const geom = feature.geometry
|
|
76
|
+
|
|
77
|
+
// Remove the rubber band point (last coordinate that follows cursor)
|
|
78
|
+
if (geom.type === 'Polygon') {
|
|
79
|
+
// Polygon coords: [v1, v2, v3, ..., rubberBand, v1(closing)]
|
|
80
|
+
// Remove rubber band (second to last) and keep the ring closed
|
|
81
|
+
const ring = geom.coordinates[0]
|
|
82
|
+
geom.coordinates[0] = [...ring.slice(0, -2), ring[0]]
|
|
83
|
+
} else {
|
|
84
|
+
// Line coords: [v1, v2, v3, ..., rubberBand]
|
|
85
|
+
// Remove the rubber band (last point)
|
|
86
|
+
geom.coordinates = geom.coordinates.slice(0, -1)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Fire draw.create to trigger the standard completion flow
|
|
90
|
+
map.fire('draw.create', { features: [feature] })
|
|
91
|
+
|
|
92
|
+
// Change mode to trigger cleanup (this calls onStop on the draw mode)
|
|
93
|
+
draw.changeMode('simple_select', { featureIds: [feature.id] })
|
|
94
|
+
}
|
|
95
|
+
drawFinish.onClick = handleFinish
|
|
96
|
+
|
|
97
|
+
// --- Undo last action (only for draw modes - edit_vertex handles its own undo)
|
|
98
|
+
const handleUndo = () => {
|
|
99
|
+
// edit_vertex mode handles its own undo via button click listener
|
|
100
|
+
if (draw.getMode() === 'edit_vertex') {
|
|
101
|
+
return
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const undoStack = mapProvider.undoStack
|
|
105
|
+
if (!undoStack || undoStack.length === 0) {
|
|
106
|
+
return
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const operation = undoStack.pop()
|
|
110
|
+
|
|
111
|
+
// Set flag to prevent button click from also adding a vertex
|
|
112
|
+
map._undoInProgress = true
|
|
113
|
+
setTimeout(() => { map._undoInProgress = false }, 100)
|
|
114
|
+
|
|
115
|
+
// Fire event for the current mode to handle
|
|
116
|
+
map.fire('draw.undo', { operation })
|
|
117
|
+
}
|
|
118
|
+
drawUndo.onClick = handleUndo
|
|
119
|
+
|
|
42
120
|
// --- Snap toggle with throttle to prevent Safari slowdown
|
|
43
121
|
let lastToggleTime = 0
|
|
44
122
|
const THROTTLE_MS = 300
|
|
45
|
-
|
|
46
123
|
const handleSnap = () => {
|
|
47
124
|
// Strict throttle - ignore clicks within throttle window
|
|
48
125
|
const now = Date.now()
|
|
@@ -88,6 +165,9 @@ export function attachEvents ({ appState, appConfig, mapState, pluginState, mapP
|
|
|
88
165
|
dispatch({ type: 'SET_FEATURE', payload: { tempFeature: newFeature }})
|
|
89
166
|
eventBus.emit('draw:create', e)
|
|
90
167
|
|
|
168
|
+
// Clear draw mode undo stack - editing starts fresh
|
|
169
|
+
mapProvider.undoStack?.clear()
|
|
170
|
+
|
|
91
171
|
// Switch straight to edit vertex mode
|
|
92
172
|
dispatch({ type: 'SET_MODE', payload: 'edit_vertex'})
|
|
93
173
|
|
|
@@ -95,6 +175,7 @@ export function attachEvents ({ appState, appConfig, mapState, pluginState, mapP
|
|
|
95
175
|
draw.changeMode('edit_vertex', {
|
|
96
176
|
container: appState.layoutRefs.viewportRef.current,
|
|
97
177
|
deleteVertexButtonId: `${appConfig.id}-draw-delete-point`,
|
|
178
|
+
undoButtonId: `${appConfig.id}-draw-undo`,
|
|
98
179
|
isPanEnabled: appState.interfaceType !== 'keyboard',
|
|
99
180
|
interfaceType: appState.interfaceType,
|
|
100
181
|
scale: { small: 1, medium: 1.5, large: 2 }[mapState.mapSize],
|
|
@@ -105,6 +186,12 @@ export function attachEvents ({ appState, appConfig, mapState, pluginState, mapP
|
|
|
105
186
|
}
|
|
106
187
|
map.on('draw.create', onCreate)
|
|
107
188
|
|
|
189
|
+
// --- A shape is updated
|
|
190
|
+
const onUpdate = (e) => {
|
|
191
|
+
eventBus.emit('draw:update', e)
|
|
192
|
+
}
|
|
193
|
+
map.on('draw.update', onUpdate)
|
|
194
|
+
|
|
108
195
|
// --- A vertex is selected
|
|
109
196
|
const onVertexSelection = (e) => {
|
|
110
197
|
dispatch({ type: 'SET_SELECTED_VERTEX_INDEX', payload: e })
|
|
@@ -112,6 +199,18 @@ export function attachEvents ({ appState, appConfig, mapState, pluginState, mapP
|
|
|
112
199
|
}
|
|
113
200
|
map.on('draw.vertexselection', onVertexSelection)
|
|
114
201
|
|
|
202
|
+
// --- Vertex count changes during drawing
|
|
203
|
+
const onVertexChange = (e) => {
|
|
204
|
+
dispatch({ type: 'SET_SELECTED_VERTEX_INDEX', payload: { index: -1, numVertecies: e.numVertecies } })
|
|
205
|
+
}
|
|
206
|
+
map.on('draw.vertexchange', onVertexChange)
|
|
207
|
+
|
|
208
|
+
// --- Undo stack changes
|
|
209
|
+
const onUndoChange = (e) => {
|
|
210
|
+
dispatch({ type: 'SET_UNDO_STACK_LENGTH', payload: e.length })
|
|
211
|
+
}
|
|
212
|
+
map.on('draw.undochange', onUndoChange)
|
|
213
|
+
|
|
115
214
|
return () => {
|
|
116
215
|
drawDone.onClick = null
|
|
117
216
|
drawAddPoint.onClick = null
|
|
@@ -122,6 +221,9 @@ export function attachEvents ({ appState, appConfig, mapState, pluginState, mapP
|
|
|
122
221
|
drawCancel.onClick = null
|
|
123
222
|
map.off('styledata', handleStyleData)
|
|
124
223
|
map.off('draw.create', onCreate)
|
|
224
|
+
map.off('draw.update', onUpdate)
|
|
125
225
|
map.off('draw.vertexselection', onVertexSelection)
|
|
226
|
+
map.off('draw.vertexchange', onVertexChange)
|
|
227
|
+
map.off('draw.undochange', onUndoChange)
|
|
126
228
|
}
|
|
127
229
|
}
|
|
@@ -2,9 +2,12 @@
|
|
|
2
2
|
import { initialState, actions } from './reducer.js'
|
|
3
3
|
import { DrawInit } from './DrawInit.jsx'
|
|
4
4
|
import { newPolygon } from './api/newPolygon.js'
|
|
5
|
+
import { newLine } from './api/newLine.js'
|
|
5
6
|
import { editFeature } from './api/editFeature.js'
|
|
6
7
|
import { addFeature } from './api/addFeature.js'
|
|
7
8
|
import { deleteFeature } from './api/deleteFeature.js'
|
|
9
|
+
import { split } from './api/split.js'
|
|
10
|
+
import { merge } from './api/merge.js'
|
|
8
11
|
|
|
9
12
|
const createButtonSlots = (showLabel) => ({
|
|
10
13
|
mobile: { slot: 'actions', showLabel },
|
|
@@ -22,39 +25,39 @@ export const manifest = {
|
|
|
22
25
|
|
|
23
26
|
buttons: [{
|
|
24
27
|
id: 'drawDone',
|
|
25
|
-
label: 'Done',
|
|
26
|
-
variant: 'primary',
|
|
28
|
+
label: ({ pluginState }) => pluginState.action ? pluginState.action.charAt(0).toUpperCase() + pluginState.action.slice(1) : 'Done',
|
|
27
29
|
hiddenWhen: ({ appState, pluginState }) => !pluginState.mode || appState.interfaceType !== 'mouse' && pluginState.mode !== 'edit_vertex',
|
|
28
|
-
enableWhen: ({ pluginState }) => !!pluginState.tempFeature,
|
|
29
|
-
...createButtonSlots(true)
|
|
30
|
+
enableWhen: ({ pluginState }) => pluginState.action ? pluginState.actionValid : !!pluginState.tempFeature,
|
|
31
|
+
...createButtonSlots(true),
|
|
32
|
+
variant: 'primary',
|
|
30
33
|
},{
|
|
31
34
|
id: 'drawAddPoint',
|
|
32
35
|
label: 'Add point',
|
|
33
36
|
variant: 'primary',
|
|
34
|
-
hiddenWhen: ({ appState, pluginState }) => pluginState.mode
|
|
37
|
+
hiddenWhen: ({ appState, pluginState }) => !['draw_polygon', 'draw_line'].includes(pluginState.mode) || appState.interfaceType === 'mouse',
|
|
35
38
|
...createButtonSlots(true)
|
|
36
39
|
},{
|
|
37
40
|
id: 'drawUndo',
|
|
38
41
|
label: 'Undo',
|
|
39
42
|
iconId: 'undo',
|
|
40
43
|
variant: 'tertiary',
|
|
41
|
-
hiddenWhen: ({ pluginState }) => !pluginState.mode,
|
|
42
|
-
enableWhen: ({ pluginState }) =>
|
|
44
|
+
hiddenWhen: ({ pluginState }) => !['draw_polygon', 'draw_line', 'edit_vertex'].includes(pluginState.mode),
|
|
45
|
+
enableWhen: ({ pluginState }) => pluginState.undoStackLength > 0,
|
|
43
46
|
...createButtonSlots(false)
|
|
44
47
|
},{
|
|
45
48
|
id: 'drawFinish',
|
|
46
49
|
label: 'Finish shape',
|
|
47
50
|
iconId: 'check',
|
|
48
51
|
variant: 'tertiary',
|
|
49
|
-
hiddenWhen: ({ pluginState }) => pluginState.mode
|
|
50
|
-
enableWhen: ({ pluginState }) => pluginState.numVertecies
|
|
52
|
+
hiddenWhen: ({ pluginState }) => !['draw_polygon', 'draw_line'].includes(pluginState.mode),
|
|
53
|
+
enableWhen: ({ pluginState }) => pluginState.numVertecies >= (pluginState.mode === 'draw_polygon' ? 3 : 2),
|
|
51
54
|
...createButtonSlots(false)
|
|
52
55
|
},{
|
|
53
56
|
id: 'drawDeletePoint',
|
|
54
57
|
label: 'Delete point',
|
|
55
58
|
iconId: 'close',
|
|
56
59
|
variant: 'tertiary',
|
|
57
|
-
enableWhen: ({ pluginState }) => pluginState.selectedVertexIndex >= 0 && pluginState.numVertecies > 3,
|
|
60
|
+
enableWhen: ({ pluginState }) => pluginState.selectedVertexIndex >= 0 && pluginState.numVertecies > (pluginState.tempFeature?.geometry?.type === 'Polygon' ? 3 : 2),
|
|
58
61
|
hiddenWhen: ({ pluginState }) => !(['simple_select', 'edit_vertex'].includes(pluginState.mode)),
|
|
59
62
|
...createButtonSlots(false)
|
|
60
63
|
},{
|
|
@@ -93,8 +96,11 @@ export const manifest = {
|
|
|
93
96
|
|
|
94
97
|
api: {
|
|
95
98
|
newPolygon,
|
|
99
|
+
newLine,
|
|
96
100
|
editFeature,
|
|
97
101
|
addFeature,
|
|
98
|
-
deleteFeature
|
|
102
|
+
deleteFeature,
|
|
103
|
+
split,
|
|
104
|
+
merge
|
|
99
105
|
}
|
|
100
106
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import MapboxDraw from '@mapbox/mapbox-gl-draw'
|
|
2
2
|
import { DisabledMode } from './modes/disabledMode.js'
|
|
3
3
|
import { EditVertexMode } from './modes/editVertexMode.js'
|
|
4
|
-
import {
|
|
4
|
+
import { DrawPolygonMode } from './modes/drawPolygonMode.js'
|
|
5
|
+
import { DrawLineMode } from './modes/drawLineMode.js'
|
|
5
6
|
import { createDrawStyles, updateDrawStyles } from './styles.js'
|
|
6
7
|
import { initMapLibreSnap } from './mapboxSnap.js'
|
|
8
|
+
import { createUndoStack } from './undoStack.js'
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* Creates and manages a MapLibre/Mapbox Draw control instance configured for polygon editing.
|
|
@@ -33,7 +35,8 @@ export const createMapboxDraw = ({ mapStyle, mapProvider, events, eventBus, snap
|
|
|
33
35
|
...MapboxDraw.modes,
|
|
34
36
|
disabled: DisabledMode,
|
|
35
37
|
edit_vertex: EditVertexMode,
|
|
36
|
-
|
|
38
|
+
draw_polygon: DrawPolygonMode,
|
|
39
|
+
draw_line: DrawLineMode
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
// --- Create MapLibre Draw instance ---
|
|
@@ -46,10 +49,53 @@ export const createMapboxDraw = ({ mapStyle, mapProvider, events, eventBus, snap
|
|
|
46
49
|
})
|
|
47
50
|
map.addControl(draw)
|
|
48
51
|
|
|
52
|
+
// Workaround: mapbox-gl-draw calls preventDefault() on touchend even in disabled mode,
|
|
53
|
+
// which prevents the browser from synthesizing a click event. We detect taps and
|
|
54
|
+
// manually dispatch a click event when in disabled mode.
|
|
55
|
+
const canvas = map.getCanvas()
|
|
56
|
+
let touchStart = null
|
|
57
|
+
|
|
58
|
+
const handleTouchStart = (e) => {
|
|
59
|
+
if (e.touches.length === 1) {
|
|
60
|
+
touchStart = { x: e.touches[0].clientX, y: e.touches[0].clientY, time: Date.now() }
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const handleTouchEnd = (e) => {
|
|
65
|
+
if (draw.getMode() !== 'disabled' || !touchStart) {
|
|
66
|
+
touchStart = null
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const touch = e.changedTouches[0]
|
|
71
|
+
const dx = touch.clientX - touchStart.x
|
|
72
|
+
const dy = touch.clientY - touchStart.y
|
|
73
|
+
const duration = Date.now() - touchStart.time
|
|
74
|
+
|
|
75
|
+
// Only synthesize click for quick taps with minimal movement
|
|
76
|
+
if (duration < 300 && Math.abs(dx) < 10 && Math.abs(dy) < 10) {
|
|
77
|
+
canvas.dispatchEvent(new MouseEvent('click', {
|
|
78
|
+
bubbles: true,
|
|
79
|
+
cancelable: true,
|
|
80
|
+
clientX: touch.clientX,
|
|
81
|
+
clientY: touch.clientY
|
|
82
|
+
}))
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
touchStart = null
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
canvas.addEventListener('touchstart', handleTouchStart, { passive: true })
|
|
89
|
+
canvas.addEventListener('touchend', handleTouchEnd, { passive: true })
|
|
90
|
+
|
|
49
91
|
// We need a reference to this
|
|
50
92
|
mapProvider.draw = draw
|
|
51
93
|
// Initialize snap as disabled (matches initialState.snap = false)
|
|
52
94
|
mapProvider.snapEnabled = false
|
|
95
|
+
// Initialize undo stack (also stored on map for mode access)
|
|
96
|
+
const undoStack = createUndoStack(map)
|
|
97
|
+
mapProvider.undoStack = undoStack
|
|
98
|
+
map._undoStack = undoStack
|
|
53
99
|
|
|
54
100
|
// --- Initialize MapboxSnap using external module ---
|
|
55
101
|
// Start with status: false to match initial snap disabled state
|
|
@@ -77,6 +123,9 @@ export const createMapboxDraw = ({ mapStyle, mapProvider, events, eventBus, snap
|
|
|
77
123
|
return {
|
|
78
124
|
draw,
|
|
79
125
|
remove() {
|
|
126
|
+
// Remove touch workaround listeners
|
|
127
|
+
canvas.removeEventListener('touchstart', handleTouchStart)
|
|
128
|
+
canvas.removeEventListener('touchend', handleTouchEnd)
|
|
80
129
|
// Remove event listeners
|
|
81
130
|
eventBus.off(events.MAP_SET_STYLE, handleSetMapStyle)
|
|
82
131
|
// Delete all features and disable draw
|
|
@@ -68,6 +68,7 @@ function applyMapboxSnapPatches(colors) {
|
|
|
68
68
|
return orig.getLines.call(this, feature, mouse, radiusArg)
|
|
69
69
|
} catch (e) {
|
|
70
70
|
// Invalid geometry - skip this feature
|
|
71
|
+
console.log(e)
|
|
71
72
|
return []
|
|
72
73
|
}
|
|
73
74
|
}
|
|
@@ -127,6 +128,7 @@ function applyMapboxSnapPatches(colors) {
|
|
|
127
128
|
return result
|
|
128
129
|
} catch (err) {
|
|
129
130
|
// Invalid geometry encountered - clear state and continue
|
|
131
|
+
console.log(err)
|
|
130
132
|
this.snapStatus = false
|
|
131
133
|
this.snapCoords = null
|
|
132
134
|
return
|