@defra/interactive-map 0.0.39-alpha → 0.0.41-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/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/control-definition.md +9 -1
- package/docs/api/slots.md +26 -5
- package/docs/api.md +4 -4
- package/docs/assets/images/slot-map.svg +61 -262
- package/docs/examples/draw-tools.mdx +3 -3
- package/docs/plugins/draw.md +80 -17
- package/docs/plugins/search.md +1 -1
- package/govuk-prototype-kit.config.json +2 -0
- package/jest.setup.js +5 -0
- package/package.json +9 -1
- package/plugins/beta/draw-es/dist/esm/im-draw-es-plugin.js +1 -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-ol/dist/esm/im-draw-ol-plugin.js +1 -1
- 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/datasets/dist/css/index.css +1 -1
- package/plugins/datasets/dist/esm/esriLayerAdapter.js +1 -1
- package/plugins/datasets/dist/esm/im-datasets-ml-adapter.js +1 -1
- package/plugins/datasets/dist/esm/im-datasets-plugin.js +1 -1
- package/plugins/datasets/dist/umd/im-datasets-esri-adapter.js +1 -1
- package/plugins/datasets/dist/umd/im-datasets-ml-adapter.js +1 -1
- package/plugins/datasets/dist/umd/im-datasets-plugin.js +1 -1
- package/plugins/datasets/dist/umd/index.js +1 -1
- package/plugins/datasets/src/adapters/esri/esriLayerAdapter.js +2 -3
- package/plugins/datasets/src/adapters/esri/esriLayerAdapter.test.js +175 -0
- package/plugins/datasets/src/adapters/esri/registry/esriDataset.js +1 -1
- package/plugins/datasets/src/adapters/esri/registry/esriDataset.test.js +55 -0
- package/plugins/datasets/src/adapters/loadLayerAdapter.js +1 -1
- package/plugins/datasets/src/adapters/loadLayerAdapter.test.js +61 -0
- package/plugins/datasets/src/adapters/maplibre/maplibreLayerAdapter.js +1 -3
- package/plugins/datasets/src/adapters/maplibre/maplibreLayerAdapter.test.js +17 -3
- package/plugins/datasets/src/api/setOpacity.test.js +9 -0
- package/plugins/datasets/src/components/LayersMenu/LayersMenu.jsx +10 -25
- package/plugins/datasets/src/components/LayersMenu/LayersMenu.test.jsx +0 -42
- package/plugins/datasets/src/datasets.scss +0 -1
- package/plugins/datasets/src/fetch/createDynamicSource.js +135 -129
- package/plugins/datasets/src/fetch/createDynamicSource.test.js +318 -0
- package/plugins/datasets/src/fetch/fetchGeoJSON.test.js +83 -0
- package/plugins/datasets/src/index.test.js +36 -0
- package/plugins/datasets/src/initialise/DatasetsInit.jsx +17 -7
- package/plugins/datasets/src/initialise/DatasetsInit.test.jsx +262 -0
- package/plugins/datasets/src/initialise/initialiseDatasets.js +16 -5
- package/plugins/datasets/src/initialise/initialiseDatasets.test.js +42 -0
- package/plugins/datasets/src/manifest.js +0 -38
- package/plugins/datasets/src/manifest.test.js +49 -0
- package/plugins/datasets/src/reducers/datasetsToMenu.test.js +54 -1
- package/plugins/datasets/src/reducers/pluginState.js +3 -16
- package/plugins/datasets/src/reducers/pluginState.test.js +23 -0
- package/plugins/datasets/src/registry/dataset.js +15 -4
- package/plugins/datasets/src/registry/dataset.test.js +61 -0
- package/plugins/datasets/src/registry/datasetRegistry.js +12 -9
- package/plugins/datasets/src/registry/datasetRegistry.test.js +17 -5
- package/plugins/datasets/src/registry/globalDataset.js +0 -3
- package/plugins/datasets/src/registry/isVisibleWhen.js +6 -3
- package/plugins/datasets/src/registry/isVisibleWhen.test.js +11 -1
- package/plugins/datasets/src/utils/bbox.test.js +125 -0
- package/plugins/draw/dist/esm/im-draw-ml-adapter.js +1 -1
- package/plugins/draw/dist/esm/im-draw-ol-adapter.js +1 -1
- package/plugins/draw/dist/esm/im-draw-plugin.js +1 -1
- package/plugins/draw/dist/esm/index.js +1 -1
- package/plugins/draw/dist/umd/im-draw-ml-adapter.js +2 -1
- package/plugins/draw/dist/umd/im-draw-ml-adapter.js.LICENSE.txt +1 -0
- package/plugins/draw/dist/umd/im-draw-ol-adapter.js +1 -1
- package/plugins/draw/dist/umd/im-draw-plugin.js +1 -1
- package/plugins/draw/dist/umd/index.js +1 -1
- package/plugins/draw/src/DrawInit.jsx +12 -4
- package/plugins/draw/src/DrawInit.test.jsx +51 -10
- package/plugins/draw/src/adapters/maplibre/MaplibreDrawAdapter.js +92 -12
- package/plugins/draw/src/adapters/maplibre/MaplibreDrawAdapter.test.js +246 -4
- package/plugins/draw/src/adapters/maplibre/mapboxDraw.js +109 -14
- package/plugins/draw/src/adapters/maplibre/mapboxDraw.test.js +174 -11
- package/plugins/draw/src/adapters/maplibre/modes/drawMode/clickHandlers.test.js +12 -0
- package/plugins/draw/src/adapters/maplibre/modes/drawMode/lifecycle.js +9 -1
- package/plugins/draw/src/adapters/maplibre/modes/drawMode/lifecycle.test.js +24 -3
- package/plugins/draw/src/adapters/maplibre/modes/drawMode/pointerHandlers.js +1 -1
- package/plugins/draw/src/adapters/maplibre/modes/drawMode/pointerHandlers.test.js +1 -1
- package/plugins/draw/src/adapters/maplibre/modes/drawPointMode.js +194 -0
- package/plugins/draw/src/adapters/maplibre/modes/drawPointMode.test.js +457 -0
- package/plugins/draw/src/adapters/maplibre/modes/editPointMode/__helpers__/harness.js +102 -0
- package/plugins/draw/src/adapters/maplibre/modes/editPointMode/keyboardHandlers.js +82 -0
- package/plugins/draw/src/adapters/maplibre/modes/editPointMode/keyboardHandlers.test.js +83 -0
- package/plugins/draw/src/adapters/maplibre/modes/editPointMode/pointOperations.js +55 -0
- package/plugins/draw/src/adapters/maplibre/modes/editPointMode/pointOperations.test.js +62 -0
- package/plugins/draw/src/adapters/maplibre/modes/editPointMode/pointerHandlers.js +138 -0
- package/plugins/draw/src/adapters/maplibre/modes/editPointMode/pointerHandlers.test.js +197 -0
- package/plugins/draw/src/adapters/maplibre/modes/editPointMode/touchHandlers.js +92 -0
- package/plugins/draw/src/adapters/maplibre/modes/editPointMode/touchHandlers.test.js +101 -0
- package/plugins/draw/src/adapters/maplibre/modes/editPointMode/undoHandlers.js +46 -0
- package/plugins/draw/src/adapters/maplibre/modes/editPointMode/undoHandlers.test.js +42 -0
- package/plugins/draw/src/adapters/maplibre/modes/editPointMode.js +151 -0
- package/plugins/draw/src/adapters/maplibre/modes/editPointMode.test.js +156 -0
- package/plugins/draw/src/adapters/maplibre/modes/editVertexMode/keyboardHandlers.js +5 -28
- package/plugins/draw/src/adapters/maplibre/modes/editVertexMode/keyboardHandlers.test.js +24 -39
- package/plugins/draw/src/adapters/maplibre/modes/editVertexMode/pointerHandlers.js +4 -5
- package/plugins/draw/src/adapters/maplibre/modes/editVertexMode/touchHandlers.js +20 -23
- package/plugins/draw/src/adapters/maplibre/modes/editVertexMode/touchHandlers.test.js +25 -5
- package/plugins/draw/src/adapters/maplibre/modes/editVertexMode/undoHandlers.js +6 -36
- package/plugins/draw/src/adapters/maplibre/modes/editVertexMode/undoHandlers.test.js +7 -49
- package/plugins/draw/src/adapters/maplibre/modes/editVertexMode/vertexOperations.js +4 -54
- package/plugins/draw/src/adapters/maplibre/modes/editVertexMode/vertexOperations.test.js +8 -33
- package/plugins/draw/src/adapters/maplibre/modes/editVertexMode.js +29 -72
- package/plugins/draw/src/adapters/maplibre/modes/editVertexMode.test.js +11 -4
- package/plugins/draw/src/adapters/maplibre/pointSymbolImages.js +158 -0
- package/plugins/draw/src/adapters/maplibre/pointSymbolImages.test.js +314 -0
- package/plugins/draw/src/adapters/maplibre/snap/prototypePatches.js +6 -1
- package/plugins/draw/src/adapters/maplibre/snap/prototypePatches.test.js +21 -0
- package/plugins/draw/src/adapters/maplibre/snap/snapInstance.js +6 -2
- package/plugins/draw/src/adapters/maplibre/snap/snapInstance.test.js +12 -0
- package/plugins/draw/src/adapters/maplibre/styles.js +38 -11
- package/plugins/draw/src/adapters/maplibre/styles.test.js +39 -0
- package/plugins/draw/src/adapters/maplibre/utils/editModeEvents.js +79 -0
- package/plugins/draw/src/adapters/maplibre/utils/editModeEvents.test.js +135 -0
- package/plugins/draw/src/adapters/maplibre/utils/geometryValidation.js +42 -0
- package/plugins/draw/src/adapters/maplibre/utils/geometryValidation.test.js +85 -0
- package/plugins/draw/src/adapters/maplibre/utils/keyboardShortcuts.js +34 -0
- package/plugins/draw/src/adapters/maplibre/utils/keyboardShortcuts.test.js +78 -0
- package/plugins/draw/src/adapters/maplibre/utils/snapHelpers.js +16 -3
- package/plugins/draw/src/adapters/maplibre/utils/snapHelpers.test.js +21 -3
- package/plugins/draw/src/adapters/maplibre/utils/snapMovement.js +59 -0
- package/plugins/draw/src/adapters/maplibre/utils/snapMovement.test.js +73 -0
- package/plugins/draw/src/adapters/maplibre/utils/touchDragMath.js +33 -0
- package/plugins/draw/src/adapters/maplibre/utils/touchDragMath.test.js +70 -0
- package/plugins/draw/src/adapters/openlayers/OLDrawAdapter.js +27 -2
- package/plugins/draw/src/adapters/openlayers/OLDrawAdapter.test.js +93 -0
- package/plugins/draw/src/adapters/openlayers/__helpers__/harness.js +9 -0
- package/plugins/draw/src/adapters/openlayers/core/OLDrawManager.js +19 -1
- package/plugins/draw/src/adapters/openlayers/core/OLDrawManager.test.js +34 -1
- package/plugins/draw/src/adapters/openlayers/core/styles.js +73 -1
- package/plugins/draw/src/adapters/openlayers/core/styles.test.js +122 -3
- package/plugins/draw/src/adapters/openlayers/draw/DrawMode.js +1 -0
- package/plugins/draw/src/adapters/openlayers/draw/DrawMode.test.js +27 -1
- package/plugins/draw/src/adapters/openlayers/draw/drawInput.js +24 -4
- package/plugins/draw/src/adapters/openlayers/draw/drawInput.test.js +47 -3
- package/plugins/draw/src/adapters/openlayers/edit/EditMode.js +1 -1
- package/plugins/draw/src/adapters/openlayers/edit/EditMode.test.js +32 -1
- package/plugins/draw/src/adapters/openlayers/edit/keyboardHandler.js +9 -5
- package/plugins/draw/src/adapters/openlayers/edit/keyboardHandler.test.js +34 -1
- package/plugins/draw/src/adapters/openlayers/edit/modifyInteraction.js +5 -3
- package/plugins/draw/src/adapters/openlayers/edit/modifyInteraction.test.js +11 -0
- package/plugins/draw/src/adapters/openlayers/edit/nudge.js +12 -5
- package/plugins/draw/src/adapters/openlayers/edit/nudge.test.js +26 -3
- package/plugins/draw/src/adapters/openlayers/edit/touchHandler.js +18 -13
- package/plugins/draw/src/adapters/openlayers/edit/touchHandler.test.js +46 -1
- package/plugins/draw/src/adapters/openlayers/olDraw.js +11 -4
- package/plugins/draw/src/adapters/openlayers/olDraw.test.js +48 -6
- package/plugins/draw/src/adapters/openlayers/point/drawPointMode.js +156 -0
- package/plugins/draw/src/adapters/openlayers/point/drawPointMode.test.js +246 -0
- package/plugins/draw/src/adapters/openlayers/point/editPointMode.js +267 -0
- package/plugins/draw/src/adapters/openlayers/point/editPointMode.test.js +327 -0
- package/plugins/draw/src/adapters/openlayers/point/pointDragInteraction.js +71 -0
- package/plugins/draw/src/adapters/openlayers/point/pointOps.js +34 -0
- package/plugins/draw/src/adapters/openlayers/point/pointOps.test.js +32 -0
- package/plugins/draw/src/adapters/openlayers/point/pointSelectionState.js +82 -0
- package/plugins/draw/src/adapters/openlayers/point/pointSelectionState.test.js +107 -0
- package/plugins/draw/src/adapters/openlayers/point/pointSymbolImages.js +83 -0
- package/plugins/draw/src/adapters/openlayers/point/pointSymbolImages.test.js +214 -0
- package/plugins/draw/src/adapters/openlayers/snap/snapIndicator.js +3 -1
- package/plugins/draw/src/adapters/openlayers/snap/snapInteraction.js +6 -9
- package/plugins/draw/src/adapters/openlayers/snap/snapInteraction.test.js +15 -4
- package/plugins/draw/src/adapters/openlayers/utils/olCoords.js +1 -1
- package/plugins/draw/src/api/addFeature.js +16 -1
- package/plugins/draw/src/api/addFeature.test.js +62 -5
- package/plugins/draw/src/api/editFeature.js +7 -4
- package/plugins/draw/src/api/editFeature.test.js +16 -0
- package/plugins/draw/src/api/newPoint.js +42 -0
- package/plugins/draw/src/api/newPoint.test.js +117 -0
- package/plugins/draw/src/api/setStyle.js +43 -0
- package/plugins/draw/src/api/setStyle.test.js +75 -0
- package/plugins/draw/src/events.js +21 -14
- package/plugins/draw/src/events.test.js +15 -1
- package/plugins/draw/src/manifest.js +18 -6
- package/plugins/draw/src/manifest.test.js +32 -1
- package/plugins/draw/src/reducer.test.js +7 -0
- package/plugins/draw/src/utils/stripInternalProperties.js +19 -0
- package/plugins/draw/src/utils/stripInternalProperties.test.js +50 -0
- package/plugins/draw/src/utils/symbolKeys.js +5 -0
- package/plugins/draw/src/validation/liveDrawChecks.test.js +54 -0
- package/plugins/draw/src/validation/liveStroke.test.js +64 -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/hooks/useCrossHairVisibility.js +12 -4
- package/plugins/interact/src/hooks/useCrossHairVisibility.test.js +88 -1
- package/plugins/interact/src/hooks/useHighlightSync.js +33 -12
- package/plugins/interact/src/hooks/useHighlightSync.test.js +96 -25
- package/plugins/interact/src/utils/featureQueries.js +18 -0
- package/plugins/interact/src/utils/featureQueries.test.js +15 -0
- package/plugins/interact/src/utils/spatial.js +9 -3
- package/plugins/interact/src/utils/spatial.test.js +12 -1
- package/plugins/map-key/dist/css/index.css +62 -0
- package/plugins/map-key/dist/esm/im-map-key-plugin.js +1 -0
- package/plugins/map-key/dist/esm/index.js +1 -0
- package/plugins/map-key/dist/umd/im-map-key-plugin.js +2 -0
- package/plugins/map-key/dist/umd/im-map-key-plugin.js.LICENSE.txt +1 -0
- package/plugins/map-key/dist/umd/index.js +2 -0
- package/plugins/map-key/dist/umd/index.js.LICENSE.txt +1 -0
- package/plugins/map-key/package.json +28 -0
- package/plugins/map-key/src/components/Key/EmptyKey.jsx +7 -0
- package/plugins/{datasets → map-key}/src/components/Key/EmptyKey.test.jsx +2 -2
- package/plugins/map-key/src/components/Key/Key.jsx +41 -0
- package/plugins/{datasets → map-key}/src/components/Key/Key.module.scss +15 -14
- package/plugins/map-key/src/components/Key/Key.test.jsx +73 -0
- package/plugins/map-key/src/components/Key/KeyGroupItem.jsx +16 -0
- package/plugins/map-key/src/components/Key/KeyGroupItem.test.jsx +53 -0
- package/plugins/map-key/src/components/Key/KeyItem.jsx +29 -0
- package/plugins/map-key/src/components/Key/KeyItem.test.jsx +67 -0
- package/plugins/map-key/src/components/Key/KeySvg.jsx +42 -0
- package/plugins/{datasets → map-key}/src/components/Key/KeySvg.test.jsx +14 -12
- package/plugins/map-key/src/components/Key/KeySvgLine.jsx +28 -0
- package/plugins/{datasets → map-key}/src/components/Key/KeySvgLine.test.jsx +1 -1
- package/plugins/map-key/src/components/Key/KeySvgPattern.jsx +23 -0
- package/plugins/{datasets → map-key}/src/components/Key/KeySvgPattern.test.jsx +2 -2
- package/plugins/map-key/src/components/Key/KeySvgRect.jsx +33 -0
- package/plugins/{datasets → map-key}/src/components/Key/KeySvgRect.test.jsx +1 -1
- package/plugins/map-key/src/components/Key/KeySvgSymbol.jsx +27 -0
- package/plugins/{datasets → map-key}/src/components/Key/KeySvgSymbol.test.jsx +5 -6
- package/plugins/map-key/src/components/Key/MapKey.jsx +50 -0
- package/plugins/map-key/src/components/Key/MapKey.test.jsx +130 -0
- package/plugins/{datasets → map-key}/src/components/Key/svgProperties.js +2 -2
- package/plugins/{datasets → map-key}/src/components/Key/svgProperties.test.js +2 -2
- package/plugins/map-key/src/index.js +13 -0
- package/plugins/map-key/src/index.test.js +31 -0
- package/plugins/map-key/src/initialise/MapKeyInit.jsx +15 -0
- package/plugins/map-key/src/initialise/MapKeyInit.test.jsx +39 -0
- package/plugins/map-key/src/manifest.js +30 -0
- package/plugins/map-key/src/manifest.test.js +63 -0
- package/plugins/map-key/src/mapKey.scss +4 -0
- package/plugins/map-key/src/registry/getDatasetRegistry.js +6 -0
- package/plugins/map-key/src/registry/getDatasetRegistry.test.js +23 -0
- package/plugins/map-key/src/registry/index.js +3 -0
- package/plugins/map-key/src/registry/index.test.js +15 -0
- package/plugins/menu/dist/css/index.css +80 -0
- package/plugins/menu/dist/esm/im-menu-plugin.js +1 -0
- package/plugins/menu/dist/esm/index.js +1 -0
- package/plugins/menu/dist/umd/im-menu-plugin.js +1 -0
- package/plugins/menu/dist/umd/index.js +2 -0
- package/plugins/menu/dist/umd/index.js.LICENSE.txt +1 -0
- package/plugins/menu/package.json +28 -0
- package/plugins/menu/src/components/Menu/CheckboxGroupWrapper.jsx +21 -0
- package/plugins/menu/src/components/Menu/GroupLegend.jsx +17 -0
- package/plugins/menu/src/components/Menu/GroupLegend.test.jsx +68 -0
- package/plugins/menu/src/components/Menu/Menu.jsx +19 -0
- package/plugins/menu/src/components/Menu/Menu.module.scss +90 -0
- package/plugins/menu/src/components/Menu/Menu.test.jsx +161 -0
- package/plugins/menu/src/components/Menu/MenuCheckbox.jsx +35 -0
- package/plugins/menu/src/components/Menu/MenuCheckbox.test.jsx +93 -0
- package/plugins/menu/src/components/Menu/MenuGroup.jsx +11 -0
- package/plugins/{datasets/src/components/LayersMenu/LayersMenuRadio.jsx → menu/src/components/Menu/MenuRadio.jsx} +6 -4
- package/plugins/{datasets/src/components/LayersMenu/LayersMenuRadio.test.jsx → menu/src/components/Menu/MenuRadio.test.jsx} +18 -18
- package/plugins/menu/src/components/Menu/RadioGroupWrapper.jsx +32 -0
- package/plugins/{datasets/src/components/LayersMenu/LayersRadioGroupWrapper.test.jsx → menu/src/components/Menu/RadioGroupWrapper.test.jsx} +21 -21
- package/plugins/menu/src/components/Menu/useIdPrefix.jsx +4 -0
- package/plugins/menu/src/index.js +13 -0
- package/plugins/menu/src/index.test.js +31 -0
- package/plugins/menu/src/initialise/MenuInit.jsx +24 -0
- package/plugins/menu/src/initialise/MenuInit.test.jsx +50 -0
- package/plugins/menu/src/initialise/createMenu.js +10 -0
- package/plugins/menu/src/initialise/createMenu.test.js +37 -0
- package/plugins/menu/src/manifest.js +35 -0
- package/plugins/menu/src/manifest.test.js +63 -0
- package/plugins/menu/src/menu.scss +4 -0
- package/plugins/menu/src/reducers/menuStateReducer.test.js +38 -0
- package/plugins/menu/src/reducers/pluginState.js +35 -0
- package/plugins/menu/src/reducers/pluginState.test.js +57 -0
- package/plugins/menu/src/registry/getDatasetRegistry.js +9 -0
- package/plugins/menu/src/registry/getDatasetRegistry.test.js +23 -0
- package/plugins/menu/src/registry/index.js +3 -0
- package/plugins/menu/src/registry/index.test.js +15 -0
- package/plugins/menu/src/registry/isVisibleWhen.js +43 -0
- package/plugins/menu/src/registry/isVisibleWhen.test.js +48 -0
- package/plugins/search/dist/css/index.css +1 -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 +7 -5
- package/plugins/search/src/components/Form/Form.module.scss +9 -20
- package/plugins/search/src/index.js +0 -1
- package/plugins/search/src/index.test.js +2 -4
- package/plugins/search/src/manifest.js +1 -1
- package/plugins/search/src/search.scss +17 -16
- package/providers/beta/openlayers/dist/esm/im-openlayers-provider.js +1 -1
- package/providers/beta/openlayers/dist/umd/im-openlayers-provider.js +1 -1
- package/providers/beta/openlayers/dist/umd/index.js +1 -1
- package/providers/beta/openlayers/src/openlayersProvider.js +4 -1
- package/providers/beta/openlayers/src/openlayersProvider.test.js +18 -0
- package/providers/beta/openlayers/src/utils/highlightFeatures.js +52 -5
- package/providers/beta/openlayers/src/utils/highlightFeatures.test.js +176 -0
- package/providers/beta/openlayers/src/utils/symbolImages.js +40 -0
- package/providers/beta/openlayers/src/utils/symbolImages.test.js +58 -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/dist/umd/index.js +1 -1
- package/providers/maplibre/src/utils/drawLayerBuckets.js +14 -0
- package/providers/maplibre/src/utils/drawLayerBuckets.test.js +18 -0
- package/providers/maplibre/src/utils/highlightFeatures.js +80 -55
- package/providers/maplibre/src/utils/highlightFeatures.test.js +156 -17
- package/providers/maplibre/src/utils/hoverCursor.js +30 -14
- package/providers/maplibre/src/utils/hoverCursor.test.js +35 -0
- package/providers/maplibre/src/utils/patternImages.js +1 -1
- package/providers/maplibre/src/utils/symbolImages.js +41 -3
- package/providers/maplibre/src/utils/symbolImages.test.js +40 -6
- package/rollup.esm.mjs +11 -1
- package/sonar-project.properties +7 -1
- package/src/App/components/Actions/Actions.test.jsx +47 -0
- package/src/App/components/Attributions/Attributions.module.scss +10 -0
- package/src/App/components/Hints/Hints.jsx +7 -2
- package/src/App/components/Hints/Hints.test.jsx +13 -0
- package/src/App/components/KeyboardHelp/KeyboardHelp.jsx +2 -3
- package/src/App/components/KeyboardHelp/KeyboardHelp.test.jsx +3 -6
- package/src/App/components/{MoveControl/MoveControl.jsx → MoveControls/MoveControls.jsx} +10 -10
- package/src/App/components/{MoveControl/MoveControl.module.scss → MoveControls/MoveControls.module.scss} +60 -29
- package/src/App/components/{MoveControl/MoveControl.test.jsx → MoveControls/MoveControls.test.jsx} +48 -48
- package/src/App/components/Panel/Panel.jsx +18 -3
- package/src/App/components/Panel/Panel.module.scss +18 -8
- package/src/App/components/Panel/Panel.test.jsx +34 -0
- package/src/App/components/Tooltip/Tooltip.test.jsx +12 -14
- package/src/App/components/Viewport/Viewport.jsx +9 -1
- package/src/App/components/Viewport/Viewport.test.jsx +11 -0
- package/src/App/hooks/useFeatureItems.js +16 -7
- package/src/App/hooks/useFeatureItems.test.js +57 -0
- package/src/App/hooks/useLayoutMeasurements.js +95 -84
- package/src/App/hooks/useLayoutMeasurements.test.js +61 -1
- package/src/App/initialiseApp.js +11 -8
- package/src/App/initialiseApp.test.js +15 -3
- package/src/App/layout/Layout.jsx +12 -11
- package/src/App/layout/Layout.test.jsx +2 -0
- package/src/App/layout/layout.module.scss +31 -17
- package/src/App/registry/keyboardShortcutRegistry.js +25 -13
- package/src/App/registry/keyboardShortcutRegistry.test.js +49 -32
- package/src/App/registry/pluginRegistry.js +2 -3
- package/src/App/registry/pluginRegistry.test.js +16 -3
- package/src/App/renderer/HtmlElementHost.jsx +18 -5
- package/src/App/renderer/HtmlElementHost.test.jsx +54 -0
- package/src/App/renderer/mapButtons.js +28 -12
- package/src/App/renderer/mapButtons.test.js +17 -4
- package/src/App/renderer/mapControls.js +3 -1
- package/src/App/renderer/mapControls.test.js +16 -0
- package/src/App/renderer/mapPanels.js +44 -9
- package/src/App/renderer/mapPanels.test.js +51 -2
- package/src/App/renderer/orderItems.js +28 -0
- package/src/App/renderer/orderItems.test.js +50 -0
- package/src/App/renderer/slotAggregator.js +2 -18
- package/src/App/renderer/slotHelpers.js +3 -1
- package/src/App/renderer/slotHelpers.test.js +5 -0
- package/src/App/renderer/slots.js +3 -0
- package/src/App/store/AppProvider.jsx +4 -2
- package/src/App/store/appDispatchMiddleware.js +1 -1
- package/src/App/store/appDispatchMiddleware.test.js +8 -0
- package/src/InteractiveMap/InteractiveMap.js +8 -2
- package/src/InteractiveMap/InteractiveMap.test.js +20 -3
- package/src/config/appConfig.js +17 -15
- package/src/config/appConfig.test.js +22 -22
- package/src/config/defaults.js +3 -1
- package/src/config/events.js +2 -0
- package/src/config/mergeConfig.js +7 -0
- package/src/config/mergeConfig.test.js +20 -0
- package/src/scss/main.scss +1 -1
- package/src/scss/settings/_colors.scss +1 -0
- package/src/scss/settings/_dimensions.scss +2 -3
- package/src/scss/settings/_transition.scss +1 -1
- package/src/services/eventBus.js +44 -0
- package/src/services/eventBus.test.js +83 -0
- package/src/services/symbolRegistry.js +1 -1
- package/src/test-utils.js +5 -0
- package/src/types.js +25 -7
- package/webpack.umd.mjs +2 -0
- package/plugins/datasets/src/components/Key/EmptyKey.jsx +0 -7
- package/plugins/datasets/src/components/Key/Key.jsx +0 -50
- package/plugins/datasets/src/components/Key/KeyGroupItem.jsx +0 -18
- package/plugins/datasets/src/components/Key/KeyItem.jsx +0 -23
- package/plugins/datasets/src/components/Key/KeySvg.jsx +0 -22
- package/plugins/datasets/src/components/Key/KeySvgLine.jsx +0 -19
- package/plugins/datasets/src/components/Key/KeySvgPattern.jsx +0 -13
- package/plugins/datasets/src/components/Key/KeySvgRect.jsx +0 -22
- package/plugins/datasets/src/components/Key/KeySvgSymbol.jsx +0 -16
- package/plugins/datasets/src/components/LayersMenu/LayersRadioGroupWrapper.jsx +0 -41
- /package/plugins/{datasets → menu}/src/reducers/menuStateReducer.js +0 -0
- /package/{providers/maplibre/src → src}/utils/rasteriseToImageData.js +0 -0
- /package/{providers/maplibre/src → src}/utils/rasteriseToImageData.test.js +0 -0
|
@@ -3,8 +3,7 @@ import {
|
|
|
3
3
|
getSnapInstance, isSnapEnabled, getSnapLngLat, triggerSnapAtPoint, clearSnapState
|
|
4
4
|
} from '../../utils/snapHelpers.js'
|
|
5
5
|
import { getCoords, coordPathToFlatIndex } from './geometryHelpers.js'
|
|
6
|
-
|
|
7
|
-
const EVENT_VERTEX_SELECTION = 'draw.vertexselection'
|
|
6
|
+
import { CUSTOM_DRAW_EVENTS } from '../../drawEvents.js'
|
|
8
7
|
|
|
9
8
|
/**
|
|
10
9
|
* Mouse/pointer interaction for the vertex-edit mode: vertex/midpoint mouse-down,
|
|
@@ -48,7 +47,7 @@ export const pointerHandlers = {
|
|
|
48
47
|
state.selectedVertexIndex = this.getVertexIndexFromMidpoint(state, coordPath)
|
|
49
48
|
state.selectedVertexType = 'vertex'
|
|
50
49
|
state.coordPath = null // Clear coordPath for midpoints
|
|
51
|
-
this.map.fire(
|
|
50
|
+
this.map.fire(CUSTOM_DRAW_EVENTS.VERTEX_SELECTION, { index: state.selectedVertexIndex, numVertecies: state.vertecies.length })
|
|
52
51
|
}
|
|
53
52
|
},
|
|
54
53
|
|
|
@@ -61,7 +60,7 @@ export const pointerHandlers = {
|
|
|
61
60
|
state.selectedVertexType = 'vertex'
|
|
62
61
|
state._isInsertingVertex = false
|
|
63
62
|
state._insertedVertexIndex = null
|
|
64
|
-
this.map.fire(
|
|
63
|
+
this.map.fire(CUSTOM_DRAW_EVENTS.VERTEX_SELECTION, { index: insertedIndex, numVertecies: state.vertecies.length })
|
|
65
64
|
return
|
|
66
65
|
}
|
|
67
66
|
DirectSelect.onClick.call(this, state, e)
|
|
@@ -116,7 +115,7 @@ export const pointerHandlers = {
|
|
|
116
115
|
state._isInsertingVertex = false
|
|
117
116
|
state._insertedVertexIndex = null
|
|
118
117
|
// DirectSelect.onMouseUp fires draw.update but not draw.selectionchange, so broadcast the count here
|
|
119
|
-
this.map.fire(
|
|
118
|
+
this.map.fire(CUSTOM_DRAW_EVENTS.VERTEX_SELECTION, { index: insertedIndex, numVertecies: state.vertecies.length })
|
|
120
119
|
},
|
|
121
120
|
|
|
122
121
|
_recordMoveUndo (state) {
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getSnapInstance, isSnapEnabled, triggerSnapAtPoint, getSnapLngLat,
|
|
3
|
-
clearSnapState, clearSnapIndicator
|
|
4
|
-
} from '../../utils/snapHelpers.js'
|
|
1
|
+
import { getSnapInstance, clearSnapState, clearSnapIndicator } from '../../utils/snapHelpers.js'
|
|
5
2
|
import { coordPathToFlatIndex } from './geometryHelpers.js'
|
|
6
|
-
import { isOnSVG } from './helpers.js'
|
|
3
|
+
import { isOnSVG, scalePoint } from './helpers.js'
|
|
7
4
|
import { createTouchTarget, applyTouchTargetColors } from '../../../../utils/touchTarget.js'
|
|
8
5
|
import { resolveColors } from '../../../../utils/resolveColors.js'
|
|
6
|
+
import { getTouchPoint, computeTouchDragAnchors, resolveTouchDragCoord } from '../../utils/touchDragMath.js'
|
|
9
7
|
|
|
10
8
|
export const applyTouchVertexColors = (el, mapStyle, pluginConfig = {}) => {
|
|
11
9
|
if (!el) { return }
|
|
@@ -50,7 +48,7 @@ export const touchHandlers = {
|
|
|
50
48
|
this.syncVertices(state)
|
|
51
49
|
|
|
52
50
|
// Push undo for the move if touch actually moved
|
|
53
|
-
if (state._touchMoved && state._moveStartPosition && state._moveStartIndex
|
|
51
|
+
if (state._touchMoved && state._moveStartPosition && state._moveStartIndex != null) {
|
|
54
52
|
this.pushUndo({
|
|
55
53
|
type: 'move_vertex',
|
|
56
54
|
featureId: state.featureId,
|
|
@@ -59,8 +57,19 @@ export const touchHandlers = {
|
|
|
59
57
|
})
|
|
60
58
|
}
|
|
61
59
|
state._moveStartPosition = null
|
|
62
|
-
state._moveStartIndex =
|
|
60
|
+
state._moveStartIndex = null
|
|
63
61
|
state._touchMoved = false
|
|
62
|
+
|
|
63
|
+
// Re-sync the target to the vertex's actual final coordinate. Mid-drag it tracks the
|
|
64
|
+
// raw finger 1:1 from its touchstart-time offset (see onTouchmove) — a mid-drag snap
|
|
65
|
+
// moves the vertex without moving the target by the same amount, leaving them out of
|
|
66
|
+
// alignment. Left uncorrected, the next onTouchstart's delta math re-anchors off that
|
|
67
|
+
// drifted position, compounding a little further with every snapped drag (same fix as
|
|
68
|
+
// editPointMode's own onTouchend, for the same reason).
|
|
69
|
+
const vertex = state.vertecies[state.selectedVertexIndex]
|
|
70
|
+
if (vertex) {
|
|
71
|
+
this.updateTouchVertexTarget(state, scalePoint(this.map.project(vertex), state.scale))
|
|
72
|
+
}
|
|
64
73
|
}
|
|
65
74
|
},
|
|
66
75
|
|
|
@@ -103,11 +112,8 @@ export const touchHandlers = {
|
|
|
103
112
|
state._moveStartIndex = state.selectedVertexIndex
|
|
104
113
|
state._touchMoved = false
|
|
105
114
|
|
|
106
|
-
const touch =
|
|
107
|
-
|
|
108
|
-
state.deltaTarget = { x: touch.x - Number.parseFloat(style.left), y: touch.y - Number.parseFloat(style.top) }
|
|
109
|
-
const vertexPt = this.map.project(vertex)
|
|
110
|
-
state.deltaVertex = { x: (touch.x / state.scale) - vertexPt.x, y: (touch.y / state.scale) - vertexPt.y }
|
|
115
|
+
const touch = getTouchPoint(e)
|
|
116
|
+
Object.assign(state, computeTouchDragAnchors(this.map, state.touchVertexTarget, touch, vertex, state.scale))
|
|
111
117
|
},
|
|
112
118
|
|
|
113
119
|
onTouchmove (state, e) {
|
|
@@ -117,17 +123,8 @@ export const touchHandlers = {
|
|
|
117
123
|
|
|
118
124
|
state._touchMoved = true
|
|
119
125
|
|
|
120
|
-
const touch =
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
let finalCoord = this.map.unproject(screenPt)
|
|
124
|
-
if (isSnapEnabled(state)) {
|
|
125
|
-
const snap = getSnapInstance(this.map)
|
|
126
|
-
triggerSnapAtPoint(snap, this.map, screenPt)
|
|
127
|
-
finalCoord = getSnapLngLat(snap) || finalCoord
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
this.moveVertex(state, finalCoord)
|
|
126
|
+
const touch = getTouchPoint(e)
|
|
127
|
+
this.moveVertex(state, resolveTouchDragCoord(this.map, state, touch))
|
|
131
128
|
this.updateTouchVertexTarget(state, { x: touch.x - state.deltaTarget.x, y: touch.y - state.deltaTarget.y })
|
|
132
129
|
}
|
|
133
130
|
}
|
|
@@ -55,6 +55,27 @@ describe('touchHandlers', () => {
|
|
|
55
55
|
expect(map._undoStack.pop()).toMatchObject({ type: 'move_vertex', vertexIndex: 1 })
|
|
56
56
|
})
|
|
57
57
|
|
|
58
|
+
// Regression: mid-drag the target tracks the raw finger 1:1 from its touchstart-time offset
|
|
59
|
+
// (see onTouchmove), so a mid-drag snap — which moves the vertex without moving the target
|
|
60
|
+
// by the same amount — leaves the two out of alignment. Re-syncing on touchend to the
|
|
61
|
+
// vertex's actual final coordinate stops that drift from compounding on the next drag.
|
|
62
|
+
test('onTouchend re-syncs the target to the selected vertex\'s actual final coordinate', () => {
|
|
63
|
+
const { ctx, state } = createHarness()
|
|
64
|
+
state.interfaceType = 'touch'
|
|
65
|
+
state.selectedVertexIndex = 1
|
|
66
|
+
ctx.moveVertex(state, { lng: 9, lat: 9 }) // as onTouchmove would have left it mid-drag
|
|
67
|
+
ctx.onTouchend(state)
|
|
68
|
+
expect(state.touchVertexTarget.style.display).toBe('block')
|
|
69
|
+
expect(state.touchVertexTarget.style.left).toBe(`${9 * 10}px`) // harness project(): coord * 10
|
|
70
|
+
expect(state.touchVertexTarget.style.top).toBe(`${9 * 10}px`)
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
test('onTouchend skips repositioning when nothing is selected', () => {
|
|
74
|
+
const { ctx, state } = createHarness()
|
|
75
|
+
state.selectedVertexIndex = -1
|
|
76
|
+
expect(() => ctx.onTouchend(state)).not.toThrow()
|
|
77
|
+
})
|
|
78
|
+
|
|
58
79
|
test('onTouchstart captures move start state, ignoring taps off the vertex/target', () => {
|
|
59
80
|
const { ctx, state } = createHarness()
|
|
60
81
|
ctx.onTouchstart(state, { target: { parentNode: document.createElement('div') }, touches: [{ clientX: 1, clientY: 1 }] })
|
|
@@ -66,6 +87,9 @@ describe('touchHandlers', () => {
|
|
|
66
87
|
expect(state._touchMoved).toBe(false)
|
|
67
88
|
})
|
|
68
89
|
|
|
90
|
+
// resolveTouchDragCoord's own snap/fallback branches are covered by
|
|
91
|
+
// utils/touchDragMath.test.js — this checks onTouchmove ignores off-target moves and wires
|
|
92
|
+
// an active snap through to the selected vertex.
|
|
69
93
|
test('onTouchmove moves the selected vertex, honouring snap, and ignores non-target moves', () => {
|
|
70
94
|
const { ctx, state, map } = createHarness()
|
|
71
95
|
state.selectedVertexIndex = 1
|
|
@@ -74,16 +98,12 @@ describe('touchHandlers', () => {
|
|
|
74
98
|
ctx.onTouchmove(state, { target: { parentNode: document.createElement('div') }, touches: [{ clientX: 5, clientY: 5 }] })
|
|
75
99
|
expect(state.vertecies[1]).toEqual([10, 0]) // off-target move ignored
|
|
76
100
|
ctx.onTouchmove(state, { target: svgTarget(state), touches: [{ clientX: 30, clientY: 40 }] })
|
|
101
|
+
expect(state._touchMoved).toBe(true)
|
|
77
102
|
|
|
78
103
|
state.getSnapEnabled = () => true
|
|
79
104
|
map._snapInstance = { status: true, snapStatus: true, snapCoords: [7, 8], snapToClosestPoint: jest.fn() }
|
|
80
105
|
ctx.onTouchmove(state, { target: svgTarget(state), touches: [{ clientX: 50, clientY: 60 }] })
|
|
81
106
|
expect(state.vertecies[1]).toEqual([7, 8])
|
|
82
|
-
|
|
83
|
-
// Snap enabled but no snap point → falls back to the pointer position
|
|
84
|
-
map._snapInstance = { status: true, snapStatus: false, snapCoords: null, snapToClosestPoint: jest.fn() }
|
|
85
|
-
ctx.onTouchmove(state, { target: svgTarget(state), touches: [{ clientX: 35, clientY: 45 }] })
|
|
86
|
-
expect(state._touchMoved).toBe(true)
|
|
87
107
|
})
|
|
88
108
|
|
|
89
109
|
test('onTap clears the snap indicator, then selects a vertex, inserts on a midpoint, or clears with no target', () => {
|
|
@@ -4,8 +4,10 @@ import {
|
|
|
4
4
|
getModifiableCoords
|
|
5
5
|
} from './geometryHelpers.js'
|
|
6
6
|
import { scalePoint } from './helpers.js'
|
|
7
|
+
import { sharedUndoHandlers } from '../../utils/geometryValidation.js'
|
|
7
8
|
|
|
8
|
-
// Map an undo-stack op type onto the geometry-change `phase` consumed by validation.
|
|
9
|
+
// Map an undo-stack op type onto the geometry-change `phase` consumed by validation. Read off
|
|
10
|
+
// `this` by the shared pushUndo mixin (utils/geometryValidation.js) — see that file's comment.
|
|
9
11
|
const UNDO_OP_PHASE = {
|
|
10
12
|
move_vertex: 'commit-move',
|
|
11
13
|
insert_vertex: 'commit-insert',
|
|
@@ -21,41 +23,9 @@ const UNDO_INVERSE_PHASE = {
|
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
export const undoHandlers = {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if (feature) {
|
|
28
|
-
this.map.fire('draw.update', {
|
|
29
|
-
features: [feature.toGeoJSON()],
|
|
30
|
-
action: 'change_coordinates'
|
|
31
|
-
})
|
|
32
|
-
}
|
|
33
|
-
},
|
|
34
|
-
|
|
35
|
-
// Emit a commit-level geometrychange (feature + change phase + vertex index) so the
|
|
36
|
-
// validation layer can accept or reject the change. Deferred a tick to avoid
|
|
37
|
-
// re-entrancy: rejection calls draw.undo(), which must run after the current
|
|
38
|
-
// mutation (and its undo bookkeeping) has fully settled.
|
|
39
|
-
emitGeometryValidation (phase, vertexIndex, featureId) {
|
|
40
|
-
if (!phase) { return }
|
|
41
|
-
setTimeout(() => {
|
|
42
|
-
const feature = this.getFeature(featureId)
|
|
43
|
-
if (!feature) { return }
|
|
44
|
-
this.map.fire('draw.geometrychange', { feature: feature.toGeoJSON(), phase, vertexIndex })
|
|
45
|
-
}, 0)
|
|
46
|
-
},
|
|
47
|
-
|
|
48
|
-
// Undo support
|
|
49
|
-
pushUndo (operation) {
|
|
50
|
-
const undoStack = this.map._undoStack
|
|
51
|
-
if (!undoStack) {
|
|
52
|
-
return
|
|
53
|
-
}
|
|
54
|
-
undoStack.push(operation)
|
|
55
|
-
// Every edit commit (move/insert/delete, via mouse or keyboard) records an undo
|
|
56
|
-
// op here, so this is the single point that feeds commit-level validation.
|
|
57
|
-
this.emitGeometryValidation(UNDO_OP_PHASE[operation.type], operation.vertexIndex, operation.featureId)
|
|
58
|
-
},
|
|
26
|
+
...sharedUndoHandlers,
|
|
27
|
+
UNDO_OP_PHASE,
|
|
28
|
+
UNDO_INVERSE_PHASE,
|
|
59
29
|
|
|
60
30
|
handleUndo (state) {
|
|
61
31
|
const undoStack = this.map._undoStack
|
|
@@ -1,52 +1,19 @@
|
|
|
1
1
|
import { createHarness } from './__helpers__/harness.js'
|
|
2
|
-
import { createUndoStack } from '../../../../utils/undoStack.js'
|
|
3
2
|
import { getRingSegments } from './geometryHelpers.js'
|
|
4
3
|
|
|
4
|
+
// fireGeometryChange/emitGeometryValidation/pushUndo are the shared mixin from
|
|
5
|
+
// utils/geometryValidation.js — their own behaviour is covered by
|
|
6
|
+
// utils/geometryValidation.test.js. This file only tests what's specific to editVertexMode:
|
|
7
|
+
// pushUndo's UNDO_OP_PHASE wiring, handleUndo's per-op-type dispatch, and the
|
|
8
|
+
// undoMoveVertex/undoInsertVertex/undoDeleteVertex ring operations themselves.
|
|
5
9
|
describe('undoHandlers', () => {
|
|
6
|
-
test('pushUndo
|
|
7
|
-
const { ctx, map } = createHarness()
|
|
8
|
-
map._undoStack = null
|
|
9
|
-
expect(() => ctx.pushUndo({ type: 'move_vertex' })).not.toThrow()
|
|
10
|
-
map._undoStack = createUndoStack(() => {})
|
|
11
|
-
ctx.pushUndo({ type: 'move_vertex' })
|
|
12
|
-
expect(map._undoStack.length).toBe(1)
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
test('pushUndo emits a deferred commit-level geometrychange with the change phase', () => {
|
|
10
|
+
test('pushUndo maps each op type to its commit phase', () => {
|
|
16
11
|
jest.useFakeTimers()
|
|
17
12
|
const { ctx, map } = createHarness()
|
|
18
13
|
map.fire.mockClear()
|
|
19
|
-
|
|
20
14
|
ctx.pushUndo({ type: 'move_vertex', featureId: 'feat-1', vertexIndex: 2 })
|
|
21
|
-
// Deferred a tick to avoid re-entrancy — nothing fired synchronously.
|
|
22
|
-
expect(map.fire).not.toHaveBeenCalledWith('draw.geometrychange', expect.anything())
|
|
23
|
-
|
|
24
|
-
jest.runAllTimers()
|
|
25
|
-
expect(map.fire).toHaveBeenCalledWith('draw.geometrychange', expect.objectContaining({
|
|
26
|
-
phase: 'commit-move',
|
|
27
|
-
vertexIndex: 2,
|
|
28
|
-
feature: expect.any(Object)
|
|
29
|
-
}))
|
|
30
|
-
jest.useRealTimers()
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
test('pushUndo does not emit a geometrychange for unmapped op types', () => {
|
|
34
|
-
jest.useFakeTimers()
|
|
35
|
-
const { ctx, map } = createHarness()
|
|
36
|
-
map.fire.mockClear()
|
|
37
|
-
ctx.pushUndo({ type: 'draw_vertex', featureId: 'feat-1' })
|
|
38
15
|
jest.runAllTimers()
|
|
39
|
-
expect(map.fire).
|
|
40
|
-
jest.useRealTimers()
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
test('emitGeometryValidation does not fire once the feature is gone', () => {
|
|
44
|
-
jest.useFakeTimers()
|
|
45
|
-
const { ctx, map } = createHarness()
|
|
46
|
-
map.fire.mockClear()
|
|
47
|
-
ctx.emitGeometryValidation('commit-move', 0, 'missing-feature')
|
|
48
|
-
jest.runAllTimers()
|
|
49
|
-
expect(map.fire).not.toHaveBeenCalledWith('draw.geometrychange', expect.anything())
|
|
16
|
+
expect(map.fire).toHaveBeenCalledWith('draw.geometrychange', expect.objectContaining({ phase: 'commit-move', vertexIndex: 2 }))
|
|
50
17
|
jest.useRealTimers()
|
|
51
18
|
})
|
|
52
19
|
|
|
@@ -82,15 +49,6 @@ describe('undoHandlers', () => {
|
|
|
82
49
|
jest.useRealTimers()
|
|
83
50
|
})
|
|
84
51
|
|
|
85
|
-
test('fireGeometryChange fires draw.update only when the feature exists', () => {
|
|
86
|
-
const { ctx, state, map } = createHarness()
|
|
87
|
-
ctx.fireGeometryChange(state)
|
|
88
|
-
expect(map.fire).toHaveBeenCalledWith('draw.update', expect.objectContaining({ action: 'change_coordinates' }))
|
|
89
|
-
map.fire.mockClear()
|
|
90
|
-
ctx.fireGeometryChange({ featureId: 'missing' })
|
|
91
|
-
expect(map.fire).not.toHaveBeenCalled()
|
|
92
|
-
})
|
|
93
|
-
|
|
94
52
|
test('undoMoveVertex restores the previous position, guarding missing feature/segment', () => {
|
|
95
53
|
const { ctx, state } = createHarness()
|
|
96
54
|
ctx.undoMoveVertex({ ...state, featureId: 'missing' }, { vertexIndex: 0, previousPosition: [0, 0], featureId: 'missing' })
|
|
@@ -4,16 +4,12 @@ import {
|
|
|
4
4
|
getSegmentForIndex,
|
|
5
5
|
getModifiableCoords
|
|
6
6
|
} from './geometryHelpers.js'
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
getSnapInstance, isSnapActive, isSnapEnabled, getSnapLngLat,
|
|
10
|
-
getSnapRadius, triggerSnapAtPoint, clearSnapIndicator
|
|
11
|
-
} from '../../utils/snapHelpers.js'
|
|
7
|
+
import { sharedSnapMovement } from '../../utils/snapMovement.js'
|
|
12
8
|
import { MIN_VERTICES } from '../../../../validation/rules.js'
|
|
13
9
|
|
|
14
|
-
const ARROW_OFFSETS = { ArrowUp: [0, -1], ArrowDown: [0, 1], ArrowLeft: [-1, 0], ArrowRight: [1, 0] }
|
|
15
|
-
|
|
16
10
|
export const vertexOperations = {
|
|
11
|
+
...sharedSnapMovement,
|
|
12
|
+
|
|
17
13
|
updateMidpoint (coordinates) {
|
|
18
14
|
setTimeout(() => {
|
|
19
15
|
this.map.getSource('mapbox-gl-draw-hot').setData({
|
|
@@ -32,58 +28,12 @@ export const vertexOperations = {
|
|
|
32
28
|
this.changeMode(state, { selectedVertexIndex: idx, selectedVertexType: type, ...(type === 'vertex' && { coordPath: this.getCoordPath(state, idx) }) })
|
|
33
29
|
},
|
|
34
30
|
|
|
35
|
-
getOffset (coord, e) {
|
|
36
|
-
const pt = this.map.project(coord)
|
|
37
|
-
const offset = e?.shiftKey ? KEYBOARD.nudgeAmount : KEYBOARD.stepAmount
|
|
38
|
-
const [dx, dy] = e ? ARROW_OFFSETS[e.key].map(v => v * offset) : [0, 0]
|
|
39
|
-
return this.map.unproject({ x: pt.x + dx, y: pt.y + dy })
|
|
40
|
-
},
|
|
41
|
-
|
|
42
31
|
getNewCoord (state, e) {
|
|
43
32
|
return this.getOffset(getCoords(this.getFeature(state.featureId))[state.selectedVertexIndex], e)
|
|
44
33
|
},
|
|
45
34
|
|
|
46
|
-
// Explicit-delta counterpart to getOffset, driven by a unit direction vector and
|
|
47
|
-
// MoveControl's own Precision toggle rather than a KeyboardEvent — used by
|
|
48
|
-
// nudgeVertexByDelta below.
|
|
49
|
-
getOffsetByDelta (coord, dx, dy, isLargeStep) {
|
|
50
|
-
const pt = this.map.project(coord)
|
|
51
|
-
const amount = isLargeStep ? KEYBOARD.stepAmount : KEYBOARD.nudgeAmount
|
|
52
|
-
return this.map.unproject({ x: pt.x + dx * amount, y: pt.y + dy * amount })
|
|
53
|
-
},
|
|
54
|
-
|
|
55
|
-
// Resolves the destination coordinate for a vertex nudge by (dx, dy) unit
|
|
56
|
-
// direction, applying snap or breaking out of an already-active one — shared by
|
|
57
|
-
// the keyboard arrow-key path (_keyboardMoveTarget) and MoveControl's
|
|
58
|
-
// explicit-delta path (nudgeVertexByDelta) so both snap identically. dx/dy are
|
|
59
|
-
// only needed for the snap-escape offset; getCandidate computes the raw,
|
|
60
|
-
// un-snapped destination the caller would otherwise have used.
|
|
61
|
-
resolveSnapTarget (state, dx, dy, currentCoord, getCandidate) {
|
|
62
|
-
const snap = getSnapInstance(this.map)
|
|
63
|
-
|
|
64
|
-
// Break out of an active snap by moving beyond the snap radius
|
|
65
|
-
if (isSnapEnabled(state) && state._isSnapped && snap) {
|
|
66
|
-
const offset = getSnapRadius(snap) + 1
|
|
67
|
-
const pt = this.map.project(currentCoord)
|
|
68
|
-
state._isSnapped = false
|
|
69
|
-
clearSnapIndicator(snap, this.map)
|
|
70
|
-
return this.map.unproject({ x: pt.x + dx * offset, y: pt.y + dy * offset })
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const newCoord = getCandidate()
|
|
74
|
-
if (isSnapEnabled(state) && snap) {
|
|
75
|
-
triggerSnapAtPoint(snap, this.map, this.map.project(newCoord))
|
|
76
|
-
if (isSnapActive(snap)) {
|
|
77
|
-
state._isSnapped = true
|
|
78
|
-
return getSnapLngLat(snap)
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
state._isSnapped = false
|
|
82
|
-
return newCoord
|
|
83
|
-
},
|
|
84
|
-
|
|
85
35
|
// Moves the selected vertex by an explicit (dx, dy) unit direction — the entry
|
|
86
|
-
// point for
|
|
36
|
+
// point for MoveControls' D-pad (see mapProvider.activeMoveTarget in events.js),
|
|
87
37
|
// as opposed to moveVertexByKey's KeyboardEvent-driven path. Each call is treated
|
|
88
38
|
// as one complete, undoable action (no held-key sequencing, since a button click
|
|
89
39
|
// has no "held" state to batch the way arrow keys do) — but still honours snap
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { createHarness, LINE } from './__helpers__/harness.js'
|
|
2
2
|
|
|
3
|
+
// getOffset/getOffsetByDelta/resolveSnapTarget are the shared mixin from
|
|
4
|
+
// utils/snapMovement.js — their own behaviour is covered by utils/snapMovement.test.js.
|
|
5
|
+
// This file only tests what's specific to a ring/segment vertex.
|
|
3
6
|
describe('vertexOperations', () => {
|
|
4
7
|
test('updateMidpoint pushes point data to the hot source', () => {
|
|
5
8
|
jest.useFakeTimers()
|
|
@@ -30,30 +33,12 @@ describe('vertexOperations', () => {
|
|
|
30
33
|
expect(api.changeMode.mock.calls.at(-1)[1].coordPath).toBeUndefined()
|
|
31
34
|
})
|
|
32
35
|
|
|
33
|
-
test('getOffset applies step/nudge amounts and returns the coord unchanged without an event', () => {
|
|
34
|
-
const { ctx } = createHarness()
|
|
35
|
-
const stepped = ctx.getOffset([5, 5], { key: 'ArrowRight', shiftKey: false })
|
|
36
|
-
const nudged = ctx.getOffset([5, 5], { key: 'ArrowRight', shiftKey: true })
|
|
37
|
-
expect(stepped.lng).not.toBe(5)
|
|
38
|
-
expect(Math.abs(nudged.lng - 5)).toBeLessThan(Math.abs(stepped.lng - 5))
|
|
39
|
-
expect(ctx.getOffset([5, 5], null)).toEqual({ lng: 5, lat: 5 })
|
|
40
|
-
})
|
|
41
|
-
|
|
42
36
|
test('getNewCoord offsets the currently selected vertex', () => {
|
|
43
37
|
const { ctx, state } = createHarness()
|
|
44
38
|
state.selectedVertexIndex = 1
|
|
45
39
|
expect(ctx.getNewCoord(state, { key: 'ArrowRight', shiftKey: false })).toHaveProperty('lng')
|
|
46
40
|
})
|
|
47
41
|
|
|
48
|
-
test('getOffsetByDelta applies step/nudge amounts along an explicit direction, mirroring getOffset\'s shiftKey polarity', () => {
|
|
49
|
-
const { ctx } = createHarness()
|
|
50
|
-
const large = ctx.getOffsetByDelta([5, 5], 1, 0, true)
|
|
51
|
-
const small = ctx.getOffsetByDelta([5, 5], 1, 0, false)
|
|
52
|
-
expect(large.lng).not.toBe(5)
|
|
53
|
-
expect(Math.abs(small.lng - 5)).toBeLessThan(Math.abs(large.lng - 5))
|
|
54
|
-
expect(ctx.getOffsetByDelta([5, 5], 0, 0, true)).toEqual({ lng: 5, lat: 5 })
|
|
55
|
-
})
|
|
56
|
-
|
|
57
42
|
test('nudgeVertexByDelta moves the selected vertex and pushes a single undo entry, or no-ops for a midpoint/no selection', () => {
|
|
58
43
|
const { ctx, state, map } = createHarness()
|
|
59
44
|
state.selectedVertexIndex = 0
|
|
@@ -73,29 +58,19 @@ describe('vertexOperations', () => {
|
|
|
73
58
|
expect(map._undoStack).toHaveLength(0)
|
|
74
59
|
})
|
|
75
60
|
|
|
76
|
-
|
|
61
|
+
// resolveSnapTarget's own snap/break-out-of-snap branches are covered by
|
|
62
|
+
// utils/snapMovement.test.js — this just checks nudgeVertexByDelta wires a snap hit
|
|
63
|
+
// through to the moved vertex, same as keyboard nudging (regression: MoveControls
|
|
64
|
+
// bypassed snap entirely before resolveSnapTarget was shared).
|
|
65
|
+
test('nudgeVertexByDelta honours an active snap', () => {
|
|
77
66
|
const { ctx, state, map } = createHarness()
|
|
78
67
|
state.selectedVertexIndex = 1
|
|
79
68
|
state.selectedVertexType = 'vertex'
|
|
80
69
|
state.getSnapEnabled = () => true
|
|
81
|
-
|
|
82
70
|
map._snapInstance = { status: true, snapStatus: true, snapCoords: [7, 8], snapToClosestPoint: jest.fn() }
|
|
83
71
|
ctx.nudgeVertexByDelta(state, 0, -1, true)
|
|
84
72
|
expect(state._isSnapped).toBe(true)
|
|
85
73
|
expect(state.vertecies[1]).toEqual([7, 8])
|
|
86
|
-
|
|
87
|
-
ctx.nudgeVertexByDelta(state, -1, 0, true) // already snapped → breaks out of the snap radius
|
|
88
|
-
expect(state._isSnapped).toBe(false)
|
|
89
|
-
|
|
90
|
-
map._snapInstance = { status: true, snapStatus: false, snapCoords: null, snapToClosestPoint: jest.fn() }
|
|
91
|
-
ctx.nudgeVertexByDelta(state, 1, 0, true) // snap enabled but inactive → raw offset coord
|
|
92
|
-
expect(state._isSnapped).toBe(false)
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
test('resolveSnapTarget is a no-op passthrough to the candidate coordinate when snap is disabled', () => {
|
|
96
|
-
const { ctx, state } = createHarness()
|
|
97
|
-
const candidate = { lng: 3, lat: 4 }
|
|
98
|
-
expect(ctx.resolveSnapTarget(state, 1, 0, [0, 0], () => candidate)).toEqual(candidate)
|
|
99
74
|
})
|
|
100
75
|
|
|
101
76
|
test('insertVertex splits a midpoint into a new vertex, records undo and selects it', () => {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import MapboxDraw from '@mapbox/mapbox-gl-draw'
|
|
2
|
-
import {
|
|
2
|
+
import { CUSTOM_DRAW_EVENTS } from '../drawEvents.js'
|
|
3
3
|
import { getCoords } from './editVertexMode/geometryHelpers.js'
|
|
4
4
|
import { scalePoint } from './editVertexMode/helpers.js'
|
|
5
|
+
import { bindEditModeListeners, unbindEditModeListeners, clearActiveSnapIndicator, buildEditModeHandlers } from '../utils/editModeEvents.js'
|
|
5
6
|
import { undoHandlers } from './editVertexMode/undoHandlers.js'
|
|
6
7
|
import { touchHandlers } from './editVertexMode/touchHandlers.js'
|
|
7
8
|
import { vertexOperations } from './editVertexMode/vertexOperations.js'
|
|
@@ -9,9 +10,6 @@ import { vertexQueries } from './editVertexMode/vertexQueries.js'
|
|
|
9
10
|
import { keyboardHandlers } from './editVertexMode/keyboardHandlers.js'
|
|
10
11
|
import { pointerHandlers } from './editVertexMode/pointerHandlers.js'
|
|
11
12
|
|
|
12
|
-
const EVENT_VERTEX_SELECTION = 'draw.vertexselection'
|
|
13
|
-
const EVENT_NUDGE_VERTEX = 'draw.nudgevertex'
|
|
14
|
-
|
|
15
13
|
export const EditVertexMode = {
|
|
16
14
|
...MapboxDraw.modes.direct_select,
|
|
17
15
|
...undoHandlers,
|
|
@@ -57,10 +55,7 @@ export const EditVertexMode = {
|
|
|
57
55
|
this.addTouchVertexTarget(state)
|
|
58
56
|
|
|
59
57
|
// Clear any snap indicator when entering edit mode
|
|
60
|
-
|
|
61
|
-
if (snap) {
|
|
62
|
-
clearSnapIndicator(snap, this.map)
|
|
63
|
-
}
|
|
58
|
+
clearActiveSnapIndicator(this.map)
|
|
64
59
|
|
|
65
60
|
// Show touch target if entering with a selected vertex on touch interface
|
|
66
61
|
if (state.interfaceType === 'touch' && state.selectedVertexIndex >= 0 && state.selectedVertexType === 'vertex') {
|
|
@@ -80,40 +75,15 @@ export const EditVertexMode = {
|
|
|
80
75
|
},
|
|
81
76
|
|
|
82
77
|
setupEventListeners (state) {
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
pointermove: bind(this.onPointerevent),
|
|
89
|
-
pointerup: bind(this.onPointerevent),
|
|
90
|
-
click: bind(this.onButtonClick),
|
|
91
|
-
touchstart: bind(this.onTouchstart),
|
|
92
|
-
touchmove: bind(this.onTouchmove),
|
|
93
|
-
touchend: bind(this.onTouchend),
|
|
94
|
-
selectionchange: bind(this.onSelectionChange),
|
|
95
|
-
scalechange: bind(this.onScaleChange),
|
|
96
|
-
update: bind(this.onUpdate),
|
|
97
|
-
move: bind(this.onMove),
|
|
98
|
-
interfacetypechange: bind(this.onInterfaceTypeChange),
|
|
99
|
-
nudgevertex: bind(this.onNudgeVertex)
|
|
100
|
-
}
|
|
78
|
+
const handlers = this.handlers = buildEditModeHandlers(this, state, {
|
|
79
|
+
nudge: this.onNudgeVertex,
|
|
80
|
+
selectionchange: this.onSelectionChange,
|
|
81
|
+
update: this.onUpdate
|
|
82
|
+
})
|
|
101
83
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
state.container.addEventListener('pointerdown', h.pointerdown)
|
|
106
|
-
state.container.addEventListener('pointermove', h.pointermove)
|
|
107
|
-
state.container.addEventListener('pointerup', h.pointerup)
|
|
108
|
-
state.container.addEventListener('touchstart', h.touchstart, { passive: false })
|
|
109
|
-
state.container.addEventListener('touchmove', h.touchmove, { passive: false })
|
|
110
|
-
state.container.addEventListener('touchend', h.touchend, { passive: false })
|
|
111
|
-
this.map.on('draw.selectionchange', h.selectionchange)
|
|
112
|
-
this.map.on('draw.scalechange', h.scalechange)
|
|
113
|
-
this.map.on('draw.update', h.update)
|
|
114
|
-
this.map.on('move', h.move)
|
|
115
|
-
this.map.on('draw.interfacetypechange', h.interfacetypechange)
|
|
116
|
-
this.map.on(EVENT_NUDGE_VERTEX, h.nudgevertex)
|
|
84
|
+
bindEditModeListeners(state, this.map, handlers)
|
|
85
|
+
this.map.on('draw.selectionchange', handlers.selectionchange)
|
|
86
|
+
this.map.on('draw.update', handlers.update)
|
|
117
87
|
},
|
|
118
88
|
|
|
119
89
|
applyVertexSelection (state, options) {
|
|
@@ -133,17 +103,17 @@ export const EditVertexMode = {
|
|
|
133
103
|
}
|
|
134
104
|
},
|
|
135
105
|
|
|
136
|
-
onSelectionChange (state,
|
|
106
|
+
onSelectionChange (state, event) {
|
|
137
107
|
// Refresh vertex list so numVertecies reflects the latest geometry (e.g. after midpoint insertion)
|
|
138
108
|
this.syncVertices(state)
|
|
139
109
|
|
|
140
|
-
const vertexCoord =
|
|
110
|
+
const vertexCoord = event.points[event.points.length - 1]?.geometry.coordinates
|
|
141
111
|
|
|
142
112
|
// Only update selectedVertexIndex from event if not keyboard mode AND event has valid vertex
|
|
143
113
|
// For keyboard mode or when we have coordPath, trust the existing selectedVertexIndex
|
|
144
114
|
if (state.interfaceType !== 'keyboard' && vertexCoord && !state.coordPath) {
|
|
145
115
|
// No coordPath available - need to search for vertex by coordinates
|
|
146
|
-
const geom =
|
|
116
|
+
const geom = event.features[0]?.geometry
|
|
147
117
|
const coords = getCoords(geom)
|
|
148
118
|
state.selectedVertexIndex = this.findVertexIndex(coords, vertexCoord, state.selectedVertexIndex)
|
|
149
119
|
}
|
|
@@ -151,7 +121,7 @@ export const EditVertexMode = {
|
|
|
151
121
|
|
|
152
122
|
state.selectedVertexType ??= state.selectedVertexIndex >= 0 ? 'vertex' : null
|
|
153
123
|
|
|
154
|
-
this.map.fire(
|
|
124
|
+
this.map.fire(CUSTOM_DRAW_EVENTS.VERTEX_SELECTION, {
|
|
155
125
|
index: state.selectedVertexType === 'vertex' ? state.selectedVertexIndex : -1,
|
|
156
126
|
numVertecies: state.vertecies.length
|
|
157
127
|
})
|
|
@@ -161,18 +131,18 @@ export const EditVertexMode = {
|
|
|
161
131
|
this.updateTouchVertexTarget(state, vertex ? scalePoint(this.map.project(vertex), state.scale) : null)
|
|
162
132
|
},
|
|
163
133
|
|
|
164
|
-
onScaleChange (state,
|
|
165
|
-
state.scale =
|
|
134
|
+
onScaleChange (state, event) {
|
|
135
|
+
state.scale = event.scale
|
|
166
136
|
},
|
|
167
137
|
|
|
168
|
-
onInterfaceTypeChange (state,
|
|
169
|
-
state.interfaceType =
|
|
138
|
+
onInterfaceTypeChange (state, event) {
|
|
139
|
+
state.interfaceType = event.interfaceType
|
|
170
140
|
const vertex = state.selectedVertexIndex >= 0 ? state.vertecies[state.selectedVertexIndex] : null
|
|
171
141
|
this.updateTouchVertexTarget(state, vertex ? scalePoint(this.map.project(vertex), state.scale) : null)
|
|
172
142
|
},
|
|
173
143
|
|
|
174
144
|
onUpdate (state) {
|
|
175
|
-
const prev = new Set(state.vertecies.map(
|
|
145
|
+
const prev = new Set(state.vertecies.map(coordinate => JSON.stringify(coordinate)))
|
|
176
146
|
if (prev.size === state.vertecies.length) {
|
|
177
147
|
return
|
|
178
148
|
}
|
|
@@ -195,19 +165,19 @@ export const EditVertexMode = {
|
|
|
195
165
|
// onUpdate hook repositions the touch target for any vertex move), moveVertex
|
|
196
166
|
// here has no equivalent hook, so the reposition has to happen explicitly —
|
|
197
167
|
// same as onMove/onSelectionChange/onInterfaceTypeChange already do.
|
|
198
|
-
onNudgeVertex (state,
|
|
199
|
-
this.nudgeVertexByDelta(state,
|
|
168
|
+
onNudgeVertex (state, event) {
|
|
169
|
+
this.nudgeVertexByDelta(state, event.dx, event.dy, event.isLargeStep)
|
|
200
170
|
const vertex = state.vertecies[state.selectedVertexIndex]
|
|
201
171
|
if (vertex) {
|
|
202
172
|
this.updateTouchVertexTarget(state, scalePoint(this.map.project(vertex), state.scale))
|
|
203
173
|
}
|
|
204
174
|
},
|
|
205
175
|
|
|
206
|
-
onButtonClick (state,
|
|
207
|
-
if (
|
|
176
|
+
onButtonClick (state, event) {
|
|
177
|
+
if (event.target.closest(`#${state.deleteVertexButtonId}`) && state.selectedVertexType === 'vertex') {
|
|
208
178
|
this.deleteVertex(state)
|
|
209
179
|
}
|
|
210
|
-
if (
|
|
180
|
+
if (event.target.closest(`#${state.undoButtonId}`)) {
|
|
211
181
|
this.handleUndo(state)
|
|
212
182
|
}
|
|
213
183
|
},
|
|
@@ -227,23 +197,10 @@ export const EditVertexMode = {
|
|
|
227
197
|
onStop (state) {
|
|
228
198
|
this.map._drawEditContainer = null
|
|
229
199
|
this.map._editingFeatureId = null
|
|
230
|
-
const
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
state.
|
|
234
|
-
state.container.removeEventListener('touchstart', h.touchstart)
|
|
235
|
-
state.container.removeEventListener('touchmove', h.touchmove)
|
|
236
|
-
state.container.removeEventListener('touchend', h.touchend)
|
|
237
|
-
this.map.off('draw.selectionchange', h.selectionchange)
|
|
238
|
-
this.map.off('draw.scalechange', h.scalechange)
|
|
239
|
-
this.map.off('draw.update', h.update)
|
|
240
|
-
this.map.off('move', h.move)
|
|
241
|
-
this.map.off('draw.interfacetypechange', h.interfacetypechange)
|
|
242
|
-
this.map.off(EVENT_NUDGE_VERTEX, h.nudgevertex)
|
|
243
|
-
this.map.dragPan.enable()
|
|
244
|
-
window.removeEventListener('click', h.click)
|
|
245
|
-
window.removeEventListener('keydown', h.keydown, { capture: true })
|
|
246
|
-
window.removeEventListener('keyup', h.keyup, { capture: true })
|
|
200
|
+
const handlers = this.handlers
|
|
201
|
+
this.map.off('draw.selectionchange', handlers.selectionchange)
|
|
202
|
+
this.map.off('draw.update', handlers.update)
|
|
203
|
+
unbindEditModeListeners(state, this.map, handlers)
|
|
247
204
|
this.hideTouchVertexIndicator(state)
|
|
248
205
|
}
|
|
249
206
|
}
|