@sakuzu/maplibre-gl-draw 1.0.0
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/CHANGELOG.md +43 -0
- package/LICENSE +661 -0
- package/README.ja.md +248 -0
- package/README.md +255 -0
- package/THIRD_PARTY_NOTICES.md +275 -0
- package/dist/api/api.d.ts +1259 -0
- package/dist/api/api.js +86 -0
- package/dist/api/context.d.ts +173 -0
- package/dist/api/context.js +193 -0
- package/dist/api/display-api.d.ts +1 -0
- package/dist/api/display-api.js +23 -0
- package/dist/api/event-api.d.ts +13 -0
- package/dist/api/event-api.js +17 -0
- package/dist/api/extension-api.d.ts +46 -0
- package/dist/api/extension-api.js +85 -0
- package/dist/api/feature-api.d.ts +11 -0
- package/dist/api/feature-api.js +101 -0
- package/dist/api/geometry/apply.d.ts +51 -0
- package/dist/api/geometry/apply.js +114 -0
- package/dist/api/geometry/boolean.d.ts +28 -0
- package/dist/api/geometry/boolean.js +65 -0
- package/dist/api/geometry/buffer.d.ts +11 -0
- package/dist/api/geometry/buffer.js +105 -0
- package/dist/api/geometry/split.d.ts +16 -0
- package/dist/api/geometry/split.js +75 -0
- package/dist/api/geometry/targets.d.ts +76 -0
- package/dist/api/geometry/targets.js +158 -0
- package/dist/api/geometry/types.d.ts +31 -0
- package/dist/api/geometry/types.js +3 -0
- package/dist/api/geometry-operations.d.ts +162 -0
- package/dist/api/geometry-operations.js +94 -0
- package/dist/api/group-api.d.ts +10 -0
- package/dist/api/group-api.js +78 -0
- package/dist/api/import-export/constants.d.ts +29 -0
- package/dist/api/import-export/constants.js +40 -0
- package/dist/api/import-export/embedded-file.d.ts +13 -0
- package/dist/api/import-export/embedded-file.js +31 -0
- package/dist/api/import-export/file-name.d.ts +10 -0
- package/dist/api/import-export/file-name.js +20 -0
- package/dist/api/import-export/format-detection.d.ts +12 -0
- package/dist/api/import-export/format-detection.js +29 -0
- package/dist/api/import-export/geojson-export.d.ts +19 -0
- package/dist/api/import-export/geojson-export.js +262 -0
- package/dist/api/import-export/geojson-import.d.ts +34 -0
- package/dist/api/import-export/geojson-import.js +538 -0
- package/dist/api/import-export/geometry-validation.d.ts +20 -0
- package/dist/api/import-export/geometry-validation.js +107 -0
- package/dist/api/import-export/image-import.d.ts +12 -0
- package/dist/api/import-export/image-import.js +53 -0
- package/dist/api/import-export/index.d.ts +9 -0
- package/dist/api/import-export/index.js +107 -0
- package/dist/api/import-export/native-format.d.ts +15 -0
- package/dist/api/import-export/native-format.js +126 -0
- package/dist/api/import-export/native-validation.d.ts +28 -0
- package/dist/api/import-export/native-validation.js +212 -0
- package/dist/api/import-export/own-property.d.ts +10 -0
- package/dist/api/import-export/own-property.js +19 -0
- package/dist/api/import-export/style-validation.d.ts +27 -0
- package/dist/api/import-export/style-validation.js +49 -0
- package/dist/api/import-export/types.d.ts +26 -0
- package/dist/api/import-export/types.js +3 -0
- package/dist/api/index.d.ts +15 -0
- package/dist/api/index.js +3 -0
- package/dist/api/input-api.d.ts +158 -0
- package/dist/api/input-api.js +144 -0
- package/dist/api/instance-api.d.ts +38 -0
- package/dist/api/instance-api.js +136 -0
- package/dist/api/layer-api.d.ts +12 -0
- package/dist/api/layer-api.js +62 -0
- package/dist/api/selection-api.d.ts +7 -0
- package/dist/api/selection-api.js +78 -0
- package/dist/api/snapping-api.d.ts +125 -0
- package/dist/api/snapping-api.js +50 -0
- package/dist/api/topology-api.d.ts +30 -0
- package/dist/api/topology-api.js +16 -0
- package/dist/api/tracing-api.d.ts +31 -0
- package/dist/api/tracing-api.js +16 -0
- package/dist/dispatcher/hit-test/box-strategies.d.ts +19 -0
- package/dist/dispatcher/hit-test/box-strategies.js +275 -0
- package/dist/dispatcher/hit-test/box-strategy.d.ts +59 -0
- package/dist/dispatcher/hit-test/box-strategy.js +37 -0
- package/dist/dispatcher/hit-test/globe-shape.d.ts +46 -0
- package/dist/dispatcher/hit-test/globe-shape.js +70 -0
- package/dist/dispatcher/hit-test/index.d.ts +14 -0
- package/dist/dispatcher/hit-test/index.js +9 -0
- package/dist/dispatcher/hit-test/local-frame.d.ts +77 -0
- package/dist/dispatcher/hit-test/local-frame.js +112 -0
- package/dist/dispatcher/hit-test/segment-grid.d.ts +32 -0
- package/dist/dispatcher/hit-test/segment-grid.js +79 -0
- package/dist/dispatcher/hit-test/service.d.ts +120 -0
- package/dist/dispatcher/hit-test/service.js +333 -0
- package/dist/dispatcher/hit-test/strategies/base.d.ts +136 -0
- package/dist/dispatcher/hit-test/strategies/base.js +66 -0
- package/dist/dispatcher/hit-test/strategies/circle.d.ts +10 -0
- package/dist/dispatcher/hit-test/strategies/circle.js +56 -0
- package/dist/dispatcher/hit-test/strategies/image.d.ts +22 -0
- package/dist/dispatcher/hit-test/strategies/image.js +115 -0
- package/dist/dispatcher/hit-test/strategies/index.d.ts +11 -0
- package/dist/dispatcher/hit-test/strategies/index.js +10 -0
- package/dist/dispatcher/hit-test/strategies/line.d.ts +17 -0
- package/dist/dispatcher/hit-test/strategies/line.js +30 -0
- package/dist/dispatcher/hit-test/strategies/multi.d.ts +44 -0
- package/dist/dispatcher/hit-test/strategies/multi.js +141 -0
- package/dist/dispatcher/hit-test/strategies/point.d.ts +20 -0
- package/dist/dispatcher/hit-test/strategies/point.js +29 -0
- package/dist/dispatcher/hit-test/strategies/polygon.d.ts +52 -0
- package/dist/dispatcher/hit-test/strategies/polygon.js +138 -0
- package/dist/dispatcher/hit-test/topmost.d.ts +48 -0
- package/dist/dispatcher/hit-test/topmost.js +157 -0
- package/dist/dispatcher/hit-test/visibility-lookup.d.ts +23 -0
- package/dist/dispatcher/hit-test/visibility-lookup.js +40 -0
- package/dist/dispatcher/index.d.ts +15 -0
- package/dist/dispatcher/index.js +3 -0
- package/dist/dispatcher/input-router.d.ts +1 -0
- package/dist/dispatcher/input-router.js +288 -0
- package/dist/dispatcher/normalizer.d.ts +1 -0
- package/dist/dispatcher/normalizer.js +513 -0
- package/dist/dispatcher/types.d.ts +144 -0
- package/dist/dispatcher/types.js +15 -0
- package/dist/display/chunk-set.d.ts +24 -0
- package/dist/display/chunk-set.js +533 -0
- package/dist/display/chunk.d.ts +1 -0
- package/dist/display/chunk.js +104 -0
- package/dist/display/columnar/index.d.ts +12 -0
- package/dist/display/columnar/index.js +13 -0
- package/dist/display/columnar/prepare.d.ts +42 -0
- package/dist/display/columnar/prepare.js +116 -0
- package/dist/display/columnar/source.d.ts +1 -0
- package/dist/display/columnar/source.js +531 -0
- package/dist/display/columnar/table.d.ts +1 -0
- package/dist/display/columnar/table.js +471 -0
- package/dist/display/columnar/types.d.ts +223 -0
- package/dist/display/columnar/types.js +3 -0
- package/dist/display/dataset.d.ts +2 -0
- package/dist/display/dataset.js +891 -0
- package/dist/display/index.d.ts +13 -0
- package/dist/display/index.js +3 -0
- package/dist/display/interaction.d.ts +1 -0
- package/dist/display/interaction.js +90 -0
- package/dist/display/manager.d.ts +1 -0
- package/dist/display/manager.js +440 -0
- package/dist/display/packed-rtree.d.ts +1 -0
- package/dist/display/packed-rtree.js +244 -0
- package/dist/display/partition.d.ts +1 -0
- package/dist/display/partition.js +226 -0
- package/dist/display/provider.d.ts +1 -0
- package/dist/display/provider.js +342 -0
- package/dist/display/retained.d.ts +40 -0
- package/dist/display/retained.js +898 -0
- package/dist/display/selection.d.ts +13 -0
- package/dist/display/selection.js +226 -0
- package/dist/display/source.d.ts +1 -0
- package/dist/display/source.js +119 -0
- package/dist/display/spatial.d.ts +1 -0
- package/dist/display/spatial.js +71 -0
- package/dist/display/style.d.ts +1 -0
- package/dist/display/style.js +126 -0
- package/dist/display/thinning.d.ts +65 -0
- package/dist/display/thinning.js +910 -0
- package/dist/display/triangulation.d.ts +1 -0
- package/dist/display/triangulation.js +0 -0
- package/dist/display/types.d.ts +561 -0
- package/dist/display/types.js +43 -0
- package/dist/extension/feature-handler.d.ts +182 -0
- package/dist/extension/feature-handler.js +3 -0
- package/dist/extension/index.d.ts +9 -0
- package/dist/extension/index.js +3 -0
- package/dist/extension/renderers.d.ts +208 -0
- package/dist/extension/renderers.js +3 -0
- package/dist/geometry/angle.d.ts +47 -0
- package/dist/geometry/angle.js +44 -0
- package/dist/geometry/bbox.d.ts +48 -0
- package/dist/geometry/bbox.js +83 -0
- package/dist/geometry/boolean.d.ts +162 -0
- package/dist/geometry/boolean.js +331 -0
- package/dist/geometry/buffer.d.ts +72 -0
- package/dist/geometry/buffer.js +218 -0
- package/dist/geometry/circle.d.ts +55 -0
- package/dist/geometry/circle.js +107 -0
- package/dist/geometry/coords.d.ts +97 -0
- package/dist/geometry/coords.js +149 -0
- package/dist/geometry/distance.d.ts +79 -0
- package/dist/geometry/distance.js +111 -0
- package/dist/geometry/errors.d.ts +74 -0
- package/dist/geometry/errors.js +104 -0
- package/dist/geometry/index.d.ts +28 -0
- package/dist/geometry/index.js +38 -0
- package/dist/geometry/measure.d.ts +81 -0
- package/dist/geometry/measure.js +236 -0
- package/dist/geometry/predicates.d.ts +62 -0
- package/dist/geometry/predicates.js +132 -0
- package/dist/geometry/simplify.d.ts +74 -0
- package/dist/geometry/simplify.js +159 -0
- package/dist/geometry/split.d.ts +68 -0
- package/dist/geometry/split.js +430 -0
- package/dist/geometry/types.d.ts +95 -0
- package/dist/geometry/types.js +3 -0
- package/dist/geometry/units.d.ts +35 -0
- package/dist/geometry/units.js +41 -0
- package/dist/index.d.ts +72 -0
- package/dist/index.js +20 -0
- package/dist/maplibre-gl-draw.d.ts +47 -0
- package/dist/maplibre-gl-draw.js +407 -0
- package/dist/messages.d.ts +64 -0
- package/dist/messages.js +36 -0
- package/dist/modes/cursor.d.ts +1 -0
- package/dist/modes/cursor.js +72 -0
- package/dist/modes/draw/circle.d.ts +1 -0
- package/dist/modes/draw/circle.js +222 -0
- package/dist/modes/draw/commit-layer.d.ts +26 -0
- package/dist/modes/draw/commit-layer.js +31 -0
- package/dist/modes/draw/freehand.d.ts +1 -0
- package/dist/modes/draw/freehand.js +264 -0
- package/dist/modes/draw/image.d.ts +1 -0
- package/dist/modes/draw/image.js +60 -0
- package/dist/modes/draw/index.d.ts +9 -0
- package/dist/modes/draw/index.js +11 -0
- package/dist/modes/draw/line.d.ts +1 -0
- package/dist/modes/draw/line.js +363 -0
- package/dist/modes/draw/point.d.ts +1 -0
- package/dist/modes/draw/point.js +87 -0
- package/dist/modes/draw/polygon.d.ts +1 -0
- package/dist/modes/draw/polygon.js +378 -0
- package/dist/modes/draw/trace-support.d.ts +79 -0
- package/dist/modes/draw/trace-support.js +161 -0
- package/dist/modes/handler.d.ts +285 -0
- package/dist/modes/handler.js +3 -0
- package/dist/modes/index.d.ts +7 -0
- package/dist/modes/index.js +3 -0
- package/dist/modes/manager.d.ts +15 -0
- package/dist/modes/manager.js +196 -0
- package/dist/modes/select/box-selection.d.ts +52 -0
- package/dist/modes/select/box-selection.js +140 -0
- package/dist/modes/select/click-handler.d.ts +32 -0
- package/dist/modes/select/click-handler.js +166 -0
- package/dist/modes/select/cursor-handler.d.ts +15 -0
- package/dist/modes/select/cursor-handler.js +59 -0
- package/dist/modes/select/drag/auxiliary.d.ts +26 -0
- package/dist/modes/select/drag/auxiliary.js +56 -0
- package/dist/modes/select/drag/intermediate-writes.d.ts +1 -0
- package/dist/modes/select/drag/intermediate-writes.js +171 -0
- package/dist/modes/select/drag/move.d.ts +24 -0
- package/dist/modes/select/drag/move.js +59 -0
- package/dist/modes/select/drag/operation.d.ts +30 -0
- package/dist/modes/select/drag/operation.js +18 -0
- package/dist/modes/select/drag/radius.d.ts +15 -0
- package/dist/modes/select/drag/radius.js +49 -0
- package/dist/modes/select/drag/transform.d.ts +17 -0
- package/dist/modes/select/drag/transform.js +155 -0
- package/dist/modes/select/drag/vertex.d.ts +17 -0
- package/dist/modes/select/drag/vertex.js +163 -0
- package/dist/modes/select/drag-handler.d.ts +1 -0
- package/dist/modes/select/drag-handler.js +254 -0
- package/dist/modes/select/hit-helpers.d.ts +40 -0
- package/dist/modes/select/hit-helpers.js +51 -0
- package/dist/modes/select/mode.d.ts +1 -0
- package/dist/modes/select/mode.js +397 -0
- package/dist/modes/select/shortcut-handler.d.ts +40 -0
- package/dist/modes/select/shortcut-handler.js +128 -0
- package/dist/operations/index.d.ts +9 -0
- package/dist/operations/index.js +3 -0
- package/dist/operations/layer-operations.d.ts +1 -0
- package/dist/operations/layer-operations.js +350 -0
- package/dist/operations/resize.d.ts +71 -0
- package/dist/operations/resize.js +252 -0
- package/dist/operations/rotate.d.ts +17 -0
- package/dist/operations/rotate.js +166 -0
- package/dist/operations/selection-operations.d.ts +20 -0
- package/dist/operations/selection-operations.js +159 -0
- package/dist/operations/shared-vertex.d.ts +1 -0
- package/dist/operations/shared-vertex.js +210 -0
- package/dist/operations/trace-graph.d.ts +96 -0
- package/dist/operations/trace-graph.js +283 -0
- package/dist/operations/vertex.d.ts +1 -0
- package/dist/operations/vertex.js +538 -0
- package/dist/plugins/index.d.ts +10 -0
- package/dist/plugins/index.js +3 -0
- package/dist/plugins/mutation-hooks.d.ts +28 -0
- package/dist/plugins/mutation-hooks.js +84 -0
- package/dist/plugins/plugin-context.d.ts +1 -0
- package/dist/plugins/plugin-context.js +367 -0
- package/dist/plugins/plugin-manager.d.ts +103 -0
- package/dist/plugins/plugin-manager.js +316 -0
- package/dist/plugins/plugin.d.ts +529 -0
- package/dist/plugins/plugin.js +3 -0
- package/dist/shared/config/constants.d.ts +66 -0
- package/dist/shared/config/constants.js +60 -0
- package/dist/shared/config/feature-style.d.ts +155 -0
- package/dist/shared/config/feature-style.js +154 -0
- package/dist/shared/config/index.d.ts +17 -0
- package/dist/shared/config/index.js +8 -0
- package/dist/shared/config/rendering.d.ts +107 -0
- package/dist/shared/config/rendering.js +33 -0
- package/dist/shared/config/selection-highlight.d.ts +29 -0
- package/dist/shared/config/selection-highlight.js +35 -0
- package/dist/shared/config/selection.d.ts +273 -0
- package/dist/shared/config/selection.js +266 -0
- package/dist/shared/config/topology.d.ts +33 -0
- package/dist/shared/config/topology.js +17 -0
- package/dist/shared/config/trace.d.ts +40 -0
- package/dist/shared/config/trace.js +17 -0
- package/dist/shared/math/angle.d.ts +21 -0
- package/dist/shared/math/angle.js +34 -0
- package/dist/shared/math/circle.d.ts +6 -0
- package/dist/shared/math/circle.js +10 -0
- package/dist/shared/math/constants.d.ts +48 -0
- package/dist/shared/math/constants.js +59 -0
- package/dist/shared/math/distance.d.ts +78 -0
- package/dist/shared/math/distance.js +147 -0
- package/dist/shared/math/globe-subdivision.d.ts +62 -0
- package/dist/shared/math/globe-subdivision.js +99 -0
- package/dist/shared/math/index.d.ts +17 -0
- package/dist/shared/math/index.js +21 -0
- package/dist/shared/math/intersection.d.ts +63 -0
- package/dist/shared/math/intersection.js +236 -0
- package/dist/shared/math/longitude.d.ts +20 -0
- package/dist/shared/math/longitude.js +31 -0
- package/dist/shared/math/mercator-plane.d.ts +27 -0
- package/dist/shared/math/mercator-plane.js +26 -0
- package/dist/shared/math/obb.d.ts +65 -0
- package/dist/shared/math/obb.js +107 -0
- package/dist/shared/math/rotation.d.ts +93 -0
- package/dist/shared/math/rotation.js +186 -0
- package/dist/shared/math/segment-grid.d.ts +69 -0
- package/dist/shared/math/segment-grid.js +159 -0
- package/dist/shared/math/transform.d.ts +140 -0
- package/dist/shared/math/transform.js +189 -0
- package/dist/shared/types/events.d.ts +128 -0
- package/dist/shared/types/events.js +3 -0
- package/dist/shared/types/model.d.ts +950 -0
- package/dist/shared/types/model.js +3 -0
- package/dist/shared/types/selection-box.d.ts +23 -0
- package/dist/shared/types/selection-box.js +3 -0
- package/dist/shared/types/style.d.ts +68 -0
- package/dist/shared/types/style.js +3 -0
- package/dist/shared/utils/color.d.ts +49 -0
- package/dist/shared/utils/color.js +180 -0
- package/dist/shared/utils/coordinates.d.ts +52 -0
- package/dist/shared/utils/coordinates.js +75 -0
- package/dist/shared/utils/embedded-image.d.ts +34 -0
- package/dist/shared/utils/embedded-image.js +161 -0
- package/dist/shared/utils/event-emitter.d.ts +262 -0
- package/dist/shared/utils/event-emitter.js +44 -0
- package/dist/shared/utils/feature-bbox.d.ts +8 -0
- package/dist/shared/utils/feature-bbox.js +207 -0
- package/dist/shared/utils/feature-segments.d.ts +23 -0
- package/dist/shared/utils/feature-segments.js +179 -0
- package/dist/shared/utils/id.d.ts +1 -0
- package/dist/shared/utils/id.js +35 -0
- package/dist/shared/utils/image.d.ts +34 -0
- package/dist/shared/utils/image.js +106 -0
- package/dist/shared/utils/index.d.ts +15 -0
- package/dist/shared/utils/index.js +24 -0
- package/dist/shared/utils/map.d.ts +26 -0
- package/dist/shared/utils/map.js +35 -0
- package/dist/shared/utils/name-generator.d.ts +197 -0
- package/dist/shared/utils/name-generator.js +337 -0
- package/dist/shared/utils/pixel-ratio.d.ts +111 -0
- package/dist/shared/utils/pixel-ratio.js +85 -0
- package/dist/shared/utils/property.d.ts +88 -0
- package/dist/shared/utils/property.js +140 -0
- package/dist/shared/utils/vertex-ref.d.ts +23 -0
- package/dist/shared/utils/vertex-ref.js +20 -0
- package/dist/snapping/custom-targets.d.ts +1 -0
- package/dist/snapping/custom-targets.js +21 -0
- package/dist/snapping/geometry.d.ts +1 -0
- package/dist/snapping/geometry.js +61 -0
- package/dist/snapping/index.d.ts +14 -0
- package/dist/snapping/index.js +4 -0
- package/dist/snapping/indicator.d.ts +19 -0
- package/dist/snapping/indicator.js +145 -0
- package/dist/snapping/providers/display.d.ts +72 -0
- package/dist/snapping/providers/display.js +268 -0
- package/dist/snapping/providers/guide.d.ts +69 -0
- package/dist/snapping/providers/guide.js +187 -0
- package/dist/snapping/providers/intersection.d.ts +1 -0
- package/dist/snapping/providers/intersection.js +92 -0
- package/dist/snapping/providers/shared.d.ts +39 -0
- package/dist/snapping/providers/shared.js +146 -0
- package/dist/snapping/providers/store.d.ts +1 -0
- package/dist/snapping/providers/store.js +132 -0
- package/dist/snapping/service.d.ts +1 -0
- package/dist/snapping/service.js +272 -0
- package/dist/snapping/types.d.ts +267 -0
- package/dist/snapping/types.js +66 -0
- package/dist/store/change-merger.d.ts +1 -0
- package/dist/store/change-merger.js +102 -0
- package/dist/store/draw-store.d.ts +1 -0
- package/dist/store/draw-store.js +396 -0
- package/dist/store/event-bridge.d.ts +1 -0
- package/dist/store/event-bridge.js +161 -0
- package/dist/store/index.d.ts +12 -0
- package/dist/store/index.js +4 -0
- package/dist/store/local-visibility.d.ts +21 -0
- package/dist/store/local-visibility.js +27 -0
- package/dist/store/lock.d.ts +67 -0
- package/dist/store/lock.js +54 -0
- package/dist/store/memory/change-bus.d.ts +60 -0
- package/dist/store/memory/change-bus.js +232 -0
- package/dist/store/memory/file-store.d.ts +15 -0
- package/dist/store/memory/file-store.js +33 -0
- package/dist/store/memory/frozen.d.ts +21 -0
- package/dist/store/memory/frozen.js +51 -0
- package/dist/store/memory/ui-state.d.ts +51 -0
- package/dist/store/memory/ui-state.js +223 -0
- package/dist/store/memory.d.ts +26 -0
- package/dist/store/memory.js +708 -0
- package/dist/store/spatial/index.d.ts +6 -0
- package/dist/store/spatial/index.js +4 -0
- package/dist/store/spatial/spatial-index.d.ts +90 -0
- package/dist/store/spatial/spatial-index.js +148 -0
- package/dist/store/spatial/store-spatial-index.d.ts +60 -0
- package/dist/store/spatial/store-spatial-index.js +125 -0
- package/dist/store/store.d.ts +417 -0
- package/dist/store/store.js +3 -0
- package/dist/store/types.d.ts +8 -0
- package/dist/store/types.js +3 -0
- package/dist/store/writable-layer.d.ts +35 -0
- package/dist/store/writable-layer.js +20 -0
- package/dist/view/cache/buffer.d.ts +28 -0
- package/dist/view/cache/buffer.js +176 -0
- package/dist/view/cache/earcut.d.ts +1 -0
- package/dist/view/cache/earcut.js +122 -0
- package/dist/view/cache/style-rule.d.ts +1 -0
- package/dist/view/cache/style-rule.js +97 -0
- package/dist/view/cache/terrain-fill.d.ts +30 -0
- package/dist/view/cache/terrain-fill.js +60 -0
- package/dist/view/cache/texture.d.ts +14 -0
- package/dist/view/cache/texture.js +292 -0
- package/dist/view/coordinator.d.ts +27 -0
- package/dist/view/coordinator.js +72 -0
- package/dist/view/feature-companion.d.ts +173 -0
- package/dist/view/feature-companion.js +108 -0
- package/dist/view/globe-subdivision.d.ts +78 -0
- package/dist/view/globe-subdivision.js +128 -0
- package/dist/view/index.d.ts +47 -0
- package/dist/view/index.js +20 -0
- package/dist/view/layer/attach.d.ts +20 -0
- package/dist/view/layer/attach.js +47 -0
- package/dist/view/layer/blend.d.ts +57 -0
- package/dist/view/layer/blend.js +14 -0
- package/dist/view/layer/custom-layer.d.ts +1 -0
- package/dist/view/layer/custom-layer.js +509 -0
- package/dist/view/layer/depth-state.d.ts +14 -0
- package/dist/view/layer/depth-state.js +44 -0
- package/dist/view/layer/display-list.d.ts +1 -0
- package/dist/view/layer/display-list.js +111 -0
- package/dist/view/layer/drape-planner.d.ts +139 -0
- package/dist/view/layer/drape-planner.js +726 -0
- package/dist/view/layer/frame-render.d.ts +57 -0
- package/dist/view/layer/frame-render.js +209 -0
- package/dist/view/layer/frame-state.d.ts +147 -0
- package/dist/view/layer/frame-state.js +484 -0
- package/dist/view/layer/gl-state.d.ts +77 -0
- package/dist/view/layer/gl-state.js +132 -0
- package/dist/view/layer/index.d.ts +6 -0
- package/dist/view/layer/index.js +5 -0
- package/dist/view/layer/render-scope.d.ts +30 -0
- package/dist/view/layer/render-scope.js +28 -0
- package/dist/view/layer/render.d.ts +87 -0
- package/dist/view/layer/render.js +187 -0
- package/dist/view/layer/renderers.d.ts +81 -0
- package/dist/view/layer/renderers.js +142 -0
- package/dist/view/layer/slot-manager.d.ts +26 -0
- package/dist/view/layer/slot-manager.js +133 -0
- package/dist/view/layer/slots.d.ts +33 -0
- package/dist/view/layer/slots.js +50 -0
- package/dist/view/layer/store-retained-bbox.d.ts +36 -0
- package/dist/view/layer/store-retained-bbox.js +188 -0
- package/dist/view/layer/store-retained-chunk.d.ts +97 -0
- package/dist/view/layer/store-retained-chunk.js +94 -0
- package/dist/view/layer/store-retained-classify.d.ts +34 -0
- package/dist/view/layer/store-retained-classify.js +88 -0
- package/dist/view/layer/store-retained-collect.d.ts +24 -0
- package/dist/view/layer/store-retained-collect.js +121 -0
- package/dist/view/layer/store-retained-coord-patch.d.ts +119 -0
- package/dist/view/layer/store-retained-coord-patch.js +168 -0
- package/dist/view/layer/store-retained-immediate.d.ts +63 -0
- package/dist/view/layer/store-retained-immediate.js +49 -0
- package/dist/view/layer/store-retained-invalidation.d.ts +96 -0
- package/dist/view/layer/store-retained-invalidation.js +192 -0
- package/dist/view/layer/store-retained.d.ts +198 -0
- package/dist/view/layer/store-retained.js +430 -0
- package/dist/view/layer/terrain-resolver.d.ts +1 -0
- package/dist/view/layer/terrain-resolver.js +174 -0
- package/dist/view/renderers/batch-manager.d.ts +61 -0
- package/dist/view/renderers/batch-manager.js +718 -0
- package/dist/view/renderers/draw-factors.d.ts +60 -0
- package/dist/view/renderers/draw-factors.js +35 -0
- package/dist/view/renderers/drawer.d.ts +1 -0
- package/dist/view/renderers/drawer.js +346 -0
- package/dist/view/renderers/image.d.ts +1 -0
- package/dist/view/renderers/image.js +255 -0
- package/dist/view/renderers/line/dash.d.ts +31 -0
- package/dist/view/renderers/line/dash.js +152 -0
- package/dist/view/renderers/line/line-geometry.d.ts +39 -0
- package/dist/view/renderers/line/line-geometry.js +460 -0
- package/dist/view/renderers/line/line-gl.d.ts +1 -0
- package/dist/view/renderers/line/line-gl.js +236 -0
- package/dist/view/renderers/line/line-shader.d.ts +1 -0
- package/dist/view/renderers/line/line-shader.js +364 -0
- package/dist/view/renderers/line/line-types.d.ts +43 -0
- package/dist/view/renderers/line/line-types.js +3 -0
- package/dist/view/renderers/line/line-uniforms.d.ts +1 -0
- package/dist/view/renderers/line/line-uniforms.js +390 -0
- package/dist/view/renderers/line/sdf-line.d.ts +92 -0
- package/dist/view/renderers/line/sdf-line.js +567 -0
- package/dist/view/renderers/point/billboard-depth.d.ts +10 -0
- package/dist/view/renderers/point/billboard-depth.js +56 -0
- package/dist/view/renderers/point/point-instance.d.ts +124 -0
- package/dist/view/renderers/point/point-instance.js +738 -0
- package/dist/view/renderers/point/point-sdf.d.ts +58 -0
- package/dist/view/renderers/point/point-sdf.js +170 -0
- package/dist/view/renderers/point/point-shape.d.ts +99 -0
- package/dist/view/renderers/point/point-shape.js +504 -0
- package/dist/view/renderers/point/point-style.d.ts +1 -0
- package/dist/view/renderers/point/point-style.js +46 -0
- package/dist/view/renderers/polygon/batch.d.ts +26 -0
- package/dist/view/renderers/polygon/batch.js +336 -0
- package/dist/view/renderers/polygon/earcut-input.d.ts +37 -0
- package/dist/view/renderers/polygon/earcut-input.js +55 -0
- package/dist/view/renderers/polygon/earcut-sliced.d.ts +69 -0
- package/dist/view/renderers/polygon/earcut-sliced.js +960 -0
- package/dist/view/renderers/polygon/fill.d.ts +74 -0
- package/dist/view/renderers/polygon/fill.js +251 -0
- package/dist/view/renderers/polygon/sdf-polygon.d.ts +62 -0
- package/dist/view/renderers/polygon/sdf-polygon.js +919 -0
- package/dist/view/renderers/polygon/terrain-cull.d.ts +3 -0
- package/dist/view/renderers/polygon/terrain-cull.js +14 -0
- package/dist/view/renderers/polygon/triangulator.d.ts +41 -0
- package/dist/view/renderers/polygon/triangulator.js +3 -0
- package/dist/view/renderers/retained.d.ts +43 -0
- package/dist/view/renderers/retained.js +3 -0
- package/dist/view/renderers/stroke.d.ts +121 -0
- package/dist/view/renderers/stroke.js +621 -0
- package/dist/view/shaders/frame.d.ts +8 -0
- package/dist/view/shaders/frame.js +37 -0
- package/dist/view/shaders/helpers.d.ts +238 -0
- package/dist/view/shaders/helpers.js +611 -0
- package/dist/view/shaders/initializer.d.ts +27 -0
- package/dist/view/shaders/initializer.js +125 -0
- package/dist/view/shaders/projection.d.ts +123 -0
- package/dist/view/shaders/projection.js +299 -0
- package/dist/view/shaders/quad-grid.d.ts +77 -0
- package/dist/view/shaders/quad-grid.js +128 -0
- package/dist/view/shaders/quad.d.ts +189 -0
- package/dist/view/shaders/quad.js +582 -0
- package/dist/view/shaders/retained-origin.d.ts +50 -0
- package/dist/view/shaders/retained-origin.js +67 -0
- package/dist/view/shaders/terrain-shade.d.ts +23 -0
- package/dist/view/shaders/terrain-shade.js +93 -0
- package/dist/view/style-rule.d.ts +166 -0
- package/dist/view/style-rule.js +300 -0
- package/dist/view/terrain/anchor.d.ts +135 -0
- package/dist/view/terrain/anchor.js +226 -0
- package/dist/view/terrain/context.d.ts +132 -0
- package/dist/view/terrain/context.js +437 -0
- package/dist/view/terrain/dem-atlas.d.ts +97 -0
- package/dist/view/terrain/dem-atlas.js +534 -0
- package/dist/view/terrain/detect.d.ts +126 -0
- package/dist/view/terrain/detect.js +198 -0
- package/dist/view/terrain/drape/bin-store.d.ts +179 -0
- package/dist/view/terrain/drape/bin-store.js +529 -0
- package/dist/view/terrain/drape/binning.d.ts +259 -0
- package/dist/view/terrain/drape/binning.js +604 -0
- package/dist/view/terrain/drape/edge-constrain.d.ts +37 -0
- package/dist/view/terrain/drape/edge-constrain.js +175 -0
- package/dist/view/terrain/drape/geometry.d.ts +95 -0
- package/dist/view/terrain/drape/geometry.js +260 -0
- package/dist/view/terrain/drape/mesh.d.ts +50 -0
- package/dist/view/terrain/drape/mesh.js +86 -0
- package/dist/view/terrain/drape/pass.d.ts +122 -0
- package/dist/view/terrain/drape/pass.js +379 -0
- package/dist/view/terrain/drape/quad-glyphs.d.ts +64 -0
- package/dist/view/terrain/drape/quad-glyphs.js +117 -0
- package/dist/view/terrain/drape/quad.d.ts +249 -0
- package/dist/view/terrain/drape/quad.js +835 -0
- package/dist/view/terrain/drape/renderer.d.ts +184 -0
- package/dist/view/terrain/drape/renderer.js +706 -0
- package/dist/view/terrain/drape/shared.d.ts +80 -0
- package/dist/view/terrain/drape/shared.js +173 -0
- package/dist/view/terrain/drape/stitch.d.ts +155 -0
- package/dist/view/terrain/drape/stitch.js +228 -0
- package/dist/view/terrain/ground.d.ts +72 -0
- package/dist/view/terrain/ground.js +151 -0
- package/dist/view/terrain/metrics.d.ts +180 -0
- package/dist/view/terrain/metrics.js +231 -0
- package/dist/view/terrain/occlusion.d.ts +11 -0
- package/dist/view/terrain/occlusion.js +129 -0
- package/dist/view/terrain/polygon.d.ts +86 -0
- package/dist/view/terrain/polygon.js +301 -0
- package/dist/view/terrain/shade.d.ts +48 -0
- package/dist/view/terrain/shade.js +45 -0
- package/dist/view/terrain/state.d.ts +99 -0
- package/dist/view/terrain/state.js +186 -0
- package/dist/view/terrain/tessellation.d.ts +265 -0
- package/dist/view/terrain/tessellation.js +924 -0
- package/dist/view/terrain/tiling.d.ts +56 -0
- package/dist/view/terrain/tiling.js +155 -0
- package/dist/view/terrain/upstream-terrain.d.ts +82 -0
- package/dist/view/terrain/upstream-terrain.js +116 -0
- package/dist/view/ui/auxiliary-handles.d.ts +151 -0
- package/dist/view/ui/auxiliary-handles.js +22 -0
- package/dist/view/ui/bounds.d.ts +53 -0
- package/dist/view/ui/bounds.js +149 -0
- package/dist/view/ui/box-selection.d.ts +1 -0
- package/dist/view/ui/box-selection.js +83 -0
- package/dist/view/ui/handle-test.d.ts +1 -0
- package/dist/view/ui/handle-test.js +437 -0
- package/dist/view/ui/handle-thinning.d.ts +122 -0
- package/dist/view/ui/handle-thinning.js +430 -0
- package/dist/view/ui/handles.d.ts +25 -0
- package/dist/view/ui/handles.js +673 -0
- package/dist/view/ui/helper.d.ts +19 -0
- package/dist/view/ui/helper.js +76 -0
- package/dist/view/ui/index.d.ts +15 -0
- package/dist/view/ui/index.js +15 -0
- package/dist/view/ui/selection-scope.d.ts +25 -0
- package/dist/view/ui/selection-scope.js +34 -0
- package/dist/view/ui/selection-ui/bounding-box.d.ts +44 -0
- package/dist/view/ui/selection-ui/bounding-box.js +240 -0
- package/dist/view/ui/selection-ui/extension-registry.d.ts +76 -0
- package/dist/view/ui/selection-ui/extension-registry.js +78 -0
- package/dist/view/ui/selection-ui/index.d.ts +12 -0
- package/dist/view/ui/selection-ui/index.js +12 -0
- package/dist/view/ui/selection-ui/renderer.d.ts +29 -0
- package/dist/view/ui/selection-ui/renderer.js +227 -0
- package/dist/view/ui/selection-ui/types.d.ts +55 -0
- package/dist/view/ui/selection-ui/types.js +3 -0
- package/dist/view/ui/selection-ui-drawer.d.ts +52 -0
- package/dist/view/ui/selection-ui-drawer.js +329 -0
- package/dist/view/ui/tentative.d.ts +1 -0
- package/dist/view/ui/tentative.js +320 -0
- package/dist/view/viewport.d.ts +119 -0
- package/dist/view/viewport.js +254 -0
- package/package.json +113 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
|
|
2
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
|
+
/**
|
|
4
|
+
* Box selection logic
|
|
5
|
+
*
|
|
6
|
+
* Responsible for handling box selection in select mode
|
|
7
|
+
*/
|
|
8
|
+
import { isLocallyHidden } from '../../store/local-visibility.js';
|
|
9
|
+
/**
|
|
10
|
+
* Detect the features inside the box
|
|
11
|
+
*
|
|
12
|
+
* First the candidates are obtained quickly through the SpatialIndex (rbush),
|
|
13
|
+
* and then a precise inside-the-box test is performed.
|
|
14
|
+
*/
|
|
15
|
+
export function queryFeaturesInBox(boxSelection, context) {
|
|
16
|
+
const { store, spatialIndex, boxSelectionRegistry } = context;
|
|
17
|
+
const rects = boxRects(boxSelection.startPoint, boxSelection.endPoint);
|
|
18
|
+
// First obtain the candidates quickly with rbush (from each part of a box that crosses the
|
|
19
|
+
// antimeridian)
|
|
20
|
+
const candidateIds = new Set();
|
|
21
|
+
for (const rect of rects) {
|
|
22
|
+
for (const id of spatialIndex.findInBounds(rect))
|
|
23
|
+
candidateIds.add(id);
|
|
24
|
+
}
|
|
25
|
+
// Perform the precise inside-the-box test on the candidates.
|
|
26
|
+
// As with the click hit test (HitTestService.hitTestAll), hidden or locked features / their
|
|
27
|
+
// layer / their group are excluded from the selection targets (this prevents the
|
|
28
|
+
// inconsistency where box selection alone could select while ignoring locks and hiding).
|
|
29
|
+
const hitIds = [];
|
|
30
|
+
for (const id of candidateIds) {
|
|
31
|
+
const feature = store.getFeature(id);
|
|
32
|
+
if (!feature)
|
|
33
|
+
continue;
|
|
34
|
+
if (!feature.visible || feature.locked)
|
|
35
|
+
continue;
|
|
36
|
+
// What this client has hidden locally is excluded from the box selection targets too
|
|
37
|
+
// (this prevents the inconsistency of being hit by the box while invisible).
|
|
38
|
+
if (isLocallyHidden(feature, store))
|
|
39
|
+
continue;
|
|
40
|
+
const layer = store.getLayer(feature.layerId);
|
|
41
|
+
if (layer && (!layer.visible || layer.locked))
|
|
42
|
+
continue;
|
|
43
|
+
if (feature.groupId) {
|
|
44
|
+
const group = store.getGroup(feature.groupId);
|
|
45
|
+
if (group && (!group.visible || group.locked))
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (rects.some((rect) => isFeatureInBox(feature, rect, boxSelectionRegistry))) {
|
|
49
|
+
hitIds.push(feature.id);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return hitIds;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* The rectangles, in longitudes within [-180, 180], that a box drawn on the screen covers
|
|
56
|
+
*
|
|
57
|
+
* The corners come from the map unprojected as they are, so a box drawn across the
|
|
58
|
+
* antimeridian has a longitude beyond ±180 at one side. It is brought back into [-180, 180]
|
|
59
|
+
* and split at the line into two rectangles, and the box as drawn is kept as well; a box as
|
|
60
|
+
* wide as the world covers every longitude.
|
|
61
|
+
*/
|
|
62
|
+
export function boxRects(start, end) {
|
|
63
|
+
const minY = Math.min(start[1], end[1]);
|
|
64
|
+
const maxY = Math.max(start[1], end[1]);
|
|
65
|
+
let minX = Math.min(start[0], end[0]);
|
|
66
|
+
let maxX = Math.max(start[0], end[0]);
|
|
67
|
+
if (maxX - minX >= 360)
|
|
68
|
+
return [{ minX: -180, minY, maxX: 180, maxY }];
|
|
69
|
+
// Features whose coordinates were stored beyond ±180 are still found by the box as drawn
|
|
70
|
+
const drawn = { minX, minY, maxX, maxY };
|
|
71
|
+
// Shift whole turns so that the west side is within [-180, 180)
|
|
72
|
+
const turns = Math.floor((minX + 180) / 360);
|
|
73
|
+
minX -= turns * 360;
|
|
74
|
+
maxX -= turns * 360;
|
|
75
|
+
const parts = maxX <= 180
|
|
76
|
+
? [{ minX, minY, maxX, maxY }]
|
|
77
|
+
: [
|
|
78
|
+
{ minX, minY, maxX: 180, maxY },
|
|
79
|
+
{ minX: -180, minY, maxX: maxX - 360, maxY },
|
|
80
|
+
];
|
|
81
|
+
return turns === 0 && parts.length === 1 ? parts : [...parts, drawn];
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Decide whether a feature is inside the box
|
|
85
|
+
*
|
|
86
|
+
* Uses BoxSelectionStrategyRegistry to perform the appropriate test per feature type.
|
|
87
|
+
* - Point: whether the center coordinate is inside the box
|
|
88
|
+
* - LineString: intersection test between the geometry and the box
|
|
89
|
+
* - Polygon: intersection test between the geometry and the box
|
|
90
|
+
* - Text/Image: intersection test between the OBB (the bounding box that accounts for rotation)
|
|
91
|
+
* and the box
|
|
92
|
+
*/
|
|
93
|
+
export function isFeatureInBox(feature, rect, boxSelectionRegistry) {
|
|
94
|
+
// Get the Strategy from the registry
|
|
95
|
+
const strategy = boxSelectionRegistry.get(feature.type);
|
|
96
|
+
if (strategy) {
|
|
97
|
+
return strategy.intersects(feature, rect);
|
|
98
|
+
}
|
|
99
|
+
// Fallback for custom types (a coordinate-based test)
|
|
100
|
+
return fallbackBoxSelection(feature, rect);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* The fallback box selection test
|
|
104
|
+
*
|
|
105
|
+
* Performs a simple coordinate-based test for feature types that are not registered.
|
|
106
|
+
*/
|
|
107
|
+
export function fallbackBoxSelection(feature, rect) {
|
|
108
|
+
const isPointInBox = (coord) => {
|
|
109
|
+
return (coord[0] >= rect.minX &&
|
|
110
|
+
coord[0] <= rect.maxX &&
|
|
111
|
+
coord[1] >= rect.minY &&
|
|
112
|
+
coord[1] <= rect.maxY);
|
|
113
|
+
};
|
|
114
|
+
const coords = feature.coordinates;
|
|
115
|
+
// When the coordinates are a single point
|
|
116
|
+
if (Array.isArray(coords) &&
|
|
117
|
+
coords.length === 2 &&
|
|
118
|
+
typeof coords[0] === 'number' &&
|
|
119
|
+
typeof coords[1] === 'number') {
|
|
120
|
+
return isPointInBox(coords);
|
|
121
|
+
}
|
|
122
|
+
// When the coordinates are an array
|
|
123
|
+
if (Array.isArray(coords) && coords.length > 0) {
|
|
124
|
+
const firstElement = coords[0];
|
|
125
|
+
// LineString form: Coordinate[]
|
|
126
|
+
if (Array.isArray(firstElement) &&
|
|
127
|
+
firstElement.length === 2 &&
|
|
128
|
+
typeof firstElement[0] === 'number') {
|
|
129
|
+
return coords.some((coord) => isPointInBox(coord));
|
|
130
|
+
}
|
|
131
|
+
// Polygon form: Coordinate[][]
|
|
132
|
+
if (Array.isArray(firstElement) && Array.isArray(firstElement[0])) {
|
|
133
|
+
const rings = coords;
|
|
134
|
+
if (rings.length === 0)
|
|
135
|
+
return false;
|
|
136
|
+
return rings[0].some((coord) => isPointInBox(coord));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* click / dblclick handling for SelectMode
|
|
3
|
+
*
|
|
4
|
+
* Single click: the priority order is plugin intercept -> vertex click -> feature selection
|
|
5
|
+
* 1. While a plugin is interacting, clicks inside its container are consumed; anything else
|
|
6
|
+
* finishes it
|
|
7
|
+
* 2. A click on a vertex handle of a singly selected feature that supports vertex editing
|
|
8
|
+
* (LineString / Polygon / the Multi types) -> vertex selection
|
|
9
|
+
* 3. Unified z traversal (hitTestTopmost) -> if it is a Store feature, the selection is
|
|
10
|
+
* updated / shift+click toggles / re-clicking an already selected feature is delegated to
|
|
11
|
+
* pluginManager.handleFeatureClick.
|
|
12
|
+
* If a dataset is in the foreground, Store features are not grabbed and it
|
|
13
|
+
* is treated as clearing the selection.
|
|
14
|
+
* If a feature companion is in the foreground, the click is consumed and passed to the
|
|
15
|
+
* provider (the selection is left unchanged)
|
|
16
|
+
*
|
|
17
|
+
* Double click: selects the feature and notifies pluginManager.handleFeatureDoubleClick
|
|
18
|
+
*/
|
|
19
|
+
import type { MouseNormalizedEvent } from '../../dispatcher/types.js';
|
|
20
|
+
import type { SelectionUIConfig } from '../../shared/config/selection.js';
|
|
21
|
+
import type { ModeContext } from '../handler.js';
|
|
22
|
+
/**
|
|
23
|
+
* The main logic of onClick
|
|
24
|
+
*/
|
|
25
|
+
export declare function handleSelectClick(event: MouseNormalizedEvent, context: ModeContext, config: SelectionUIConfig): void;
|
|
26
|
+
/**
|
|
27
|
+
* The main logic of onDoubleClick
|
|
28
|
+
*
|
|
29
|
+
* A double click on a feature is consumed (its default action is prevented, so MapLibre does
|
|
30
|
+
* not zoom); a double click on the empty map is left to MapLibre.
|
|
31
|
+
*/
|
|
32
|
+
export declare function handleSelectDoubleClick(event: MouseNormalizedEvent, context: ModeContext): void;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
|
|
2
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
|
+
import { createCoordinateTransform } from '../../shared/math/index.js';
|
|
4
|
+
import { supportsVertexEditing } from '../../shared/utils/coordinates.js';
|
|
5
|
+
import { hasVertexRef, isSameVertexRef } from '../../shared/utils/vertex-ref.js';
|
|
6
|
+
import { getDisplayFeatures } from '../../store/local-visibility.js';
|
|
7
|
+
import { notifyFeatureCompanionClick } from '../../view/feature-companion.js';
|
|
8
|
+
import { hitTestHandles } from '../../view/ui/handle-test.js';
|
|
9
|
+
import { getSelectedFeatures } from '../../view/ui/helper.js';
|
|
10
|
+
/**
|
|
11
|
+
* The main logic of onClick
|
|
12
|
+
*/
|
|
13
|
+
export function handleSelectClick(event, context, config) {
|
|
14
|
+
if (handlePluginInteractionClick(event, context)) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const { store } = context;
|
|
18
|
+
const selection = store.getSelection();
|
|
19
|
+
const selectedIds = selection.type === 'feature' ? selection.ids : [];
|
|
20
|
+
if (handleVertexClick(event, selectedIds, context, config)) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
store.setSelectedVertices(null);
|
|
24
|
+
handleFeatureClick(event, selection, selectedIds, context);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The main logic of onDoubleClick
|
|
28
|
+
*
|
|
29
|
+
* A double click on a feature is consumed (its default action is prevented, so MapLibre does
|
|
30
|
+
* not zoom); a double click on the empty map is left to MapLibre.
|
|
31
|
+
*/
|
|
32
|
+
export function handleSelectDoubleClick(event, context) {
|
|
33
|
+
if (context.pluginManager?.isPluginInteracting())
|
|
34
|
+
return;
|
|
35
|
+
const { store } = context;
|
|
36
|
+
const orderedFeatures = getDisplayFeatures(store);
|
|
37
|
+
// Store features are not grabbed when a dataset is in the foreground
|
|
38
|
+
const top = context.hitTestTopmost(event.point, { orderedFeatures });
|
|
39
|
+
if (top?.kind !== 'store')
|
|
40
|
+
return;
|
|
41
|
+
event.originalEvent.preventDefault();
|
|
42
|
+
const filtered = context.pluginManager?.filterSelectionCandidates([top.feature.id]) ?? [
|
|
43
|
+
top.feature.id,
|
|
44
|
+
];
|
|
45
|
+
if (filtered.length > 0) {
|
|
46
|
+
store.setSelection('feature', filtered);
|
|
47
|
+
}
|
|
48
|
+
context.pluginManager?.handleFeatureDoubleClick(top.feature.id);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Click handling during a plugin interaction
|
|
52
|
+
*
|
|
53
|
+
* @returns true when the click was consumed (= the caller skips the rest of the handling)
|
|
54
|
+
*/
|
|
55
|
+
function handlePluginInteractionClick(event, context) {
|
|
56
|
+
const pm = context.pluginManager;
|
|
57
|
+
if (!pm?.isPluginInteracting())
|
|
58
|
+
return false;
|
|
59
|
+
const container = pm.getPluginInteractionContainer();
|
|
60
|
+
if (container) {
|
|
61
|
+
const target = event.originalEvent.target;
|
|
62
|
+
if (container.contains(target)) {
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
pm.finishPluginInteraction();
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Click handling for vertex handles
|
|
71
|
+
*
|
|
72
|
+
* @returns true when a vertex was selected
|
|
73
|
+
*/
|
|
74
|
+
function handleVertexClick(event, selectedIds, context, config) {
|
|
75
|
+
if (selectedIds.length !== 1)
|
|
76
|
+
return false;
|
|
77
|
+
const { store, map } = context;
|
|
78
|
+
const selectedFeatures = getSelectedFeatures(store);
|
|
79
|
+
const feature = selectedFeatures[0];
|
|
80
|
+
// Only types that support vertex editing (LineString / Polygon / the Multi types) are subject
|
|
81
|
+
// to vertex selection
|
|
82
|
+
if (!feature || !supportsVertexEditing(feature.type))
|
|
83
|
+
return false;
|
|
84
|
+
const transform = createCoordinateTransform(map);
|
|
85
|
+
const zoom = map.getZoom();
|
|
86
|
+
const handleHit = hitTestHandles(event.point, selectedFeatures, transform, config, zoom, context.selectionScope);
|
|
87
|
+
if (handleHit?.type !== 'vertex' || handleHit.vertexRef === undefined) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
const featureId = handleHit.featureId;
|
|
91
|
+
if (!featureId)
|
|
92
|
+
return false;
|
|
93
|
+
const vertexRef = handleHit.vertexRef;
|
|
94
|
+
const currentVertexSelection = store.getSelectedVertices();
|
|
95
|
+
if (event.modifiers.shift && currentVertexSelection?.featureId === featureId) {
|
|
96
|
+
// Shift+click: add / remove a vertex of the same feature
|
|
97
|
+
const refs = currentVertexSelection.vertexIndices;
|
|
98
|
+
if (hasVertexRef(refs, vertexRef)) {
|
|
99
|
+
const newRefs = refs.filter((r) => !isSameVertexRef(r, vertexRef));
|
|
100
|
+
store.setSelectedVertices(newRefs.length === 0 ? null : { featureId, vertexIndices: newRefs });
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
store.setSelectedVertices({ featureId, vertexIndices: [...refs, vertexRef] });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
store.setSelectedVertices({ featureId, vertexIndices: [vertexRef] });
|
|
108
|
+
}
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Feature selection handling
|
|
113
|
+
*/
|
|
114
|
+
function handleFeatureClick(event, selection, selectedIds, context) {
|
|
115
|
+
const { store } = context;
|
|
116
|
+
const orderedFeatures = getDisplayFeatures(store);
|
|
117
|
+
const top = context.hitTestTopmost(event.point, { orderedFeatures });
|
|
118
|
+
// A feature companion is in the foreground: the provider receives the click and core changes
|
|
119
|
+
// the selection in no way at all (not even clearing it as an empty click would). Core does not
|
|
120
|
+
// know what the companion is, so its job ends at consuming the click and reporting it.
|
|
121
|
+
if (top?.kind === 'companion') {
|
|
122
|
+
notifyFeatureCompanionClick(context.featureCompanions, top.companion);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
// When there is nothing, and when a dataset is in the foreground, Store
|
|
126
|
+
// features are not grabbed. A dataset's click fires only when the intercepting side
|
|
127
|
+
// (display/interaction) is interactive.
|
|
128
|
+
if (top?.kind !== 'store') {
|
|
129
|
+
if (!event.modifiers.shift) {
|
|
130
|
+
store.setSelection(null, []);
|
|
131
|
+
}
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const feature = top.feature;
|
|
135
|
+
// Re-clicking an already selected feature -> delegate to the plugins
|
|
136
|
+
if (!event.modifiers.shift && selectedIds.length === 1 && selectedIds.includes(feature.id)) {
|
|
137
|
+
if (context.pluginManager?.handleFeatureClick(feature.id)) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// Update the selection
|
|
142
|
+
const candidateIds = event.modifiers.shift
|
|
143
|
+
? toggleSelection(selection, feature.id)
|
|
144
|
+
: [feature.id];
|
|
145
|
+
const filtered = context.pluginManager?.filterSelectionCandidates(candidateIds) ?? candidateIds;
|
|
146
|
+
if (filtered.length === 0) {
|
|
147
|
+
store.setSelection(null, []);
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
store.setSelection('feature', filtered);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Toggling the selection with Shift+click
|
|
155
|
+
*/
|
|
156
|
+
function toggleSelection(selection, featureId) {
|
|
157
|
+
const current = selection.type === 'feature' ? [...selection.ids] : [];
|
|
158
|
+
const index = current.indexOf(featureId);
|
|
159
|
+
if (index === -1) {
|
|
160
|
+
current.push(featureId);
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
current.splice(index, 1);
|
|
164
|
+
}
|
|
165
|
+
return current;
|
|
166
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cursor control for SelectMode (onMouseMove)
|
|
3
|
+
*
|
|
4
|
+
* 1. There is a selected feature and a handle was hit -> the cursor that matches the handle kind
|
|
5
|
+
* (move / resize / vertex, etc.)
|
|
6
|
+
* 1.5. A selection-independent auxiliary handle (provided by an extension implementation) was
|
|
7
|
+
* hit -> that handle's cursor
|
|
8
|
+
* 2. Otherwise, a Store feature or an interactive dataset is in the very
|
|
9
|
+
* foreground -> 'pointer'
|
|
10
|
+
* 3. Otherwise (a dataset that merely occludes / nothing) -> 'default'
|
|
11
|
+
*/
|
|
12
|
+
import type { MouseNormalizedEvent } from '../../dispatcher/types.js';
|
|
13
|
+
import type { SelectionUIConfig } from '../../shared/config/selection.js';
|
|
14
|
+
import type { ModeContext } from '../handler.js';
|
|
15
|
+
export declare function updateCursorForSelection(event: MouseNormalizedEvent, context: ModeContext, config: SelectionUIConfig): void;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
|
|
2
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
|
+
import { createCoordinateTransform } from '../../shared/math/index.js';
|
|
4
|
+
import { getDisplayFeatures } from '../../store/local-visibility.js';
|
|
5
|
+
import { isInteractionBlocked } from '../../store/lock.js';
|
|
6
|
+
import { getCursorForHandle, hitTestGlobalAuxiliaryHandles, hitTestHandles, } from '../../view/ui/handle-test.js';
|
|
7
|
+
import { computeSelectionBoundingBox, getSelectedFeatureIds, getSelectedFeatures, } from '../../view/ui/helper.js';
|
|
8
|
+
import { getAdditionalResizeHandlesCallback, getAuxiliaryHandlesCallback, getGlobalAuxiliaryHandlesCallback, } from './hit-helpers.js';
|
|
9
|
+
export function updateCursorForSelection(event, context, config) {
|
|
10
|
+
const { store, map } = context;
|
|
11
|
+
// Group / layer selections are also resolved to their members (so the operation cursor is
|
|
12
|
+
// shown over a group).
|
|
13
|
+
const selectedIds = getSelectedFeatureIds(store);
|
|
14
|
+
const canvas = map.getCanvas();
|
|
15
|
+
const transform = createCoordinateTransform(map);
|
|
16
|
+
// Handle hit test on the selected features
|
|
17
|
+
// No operation cursor (move / resize, etc.) is shown for a selection whose editing operations
|
|
18
|
+
// are suppressed (effective lock / read-only / interaction lock). Dragging is rejected by
|
|
19
|
+
// startDrag with the same predicate, so the cursor alone would be a lie suggesting it is
|
|
20
|
+
// possible. It falls through to the feature hit test below (pointer), matching the operation
|
|
21
|
+
// that is actually possible: "it can be selected by clicking".
|
|
22
|
+
if (selectedIds.length > 0) {
|
|
23
|
+
const selectedFeatures = getSelectedFeatures(store);
|
|
24
|
+
const blocked = selectedFeatures.some((f) => isInteractionBlocked(f, store));
|
|
25
|
+
const bbox = blocked
|
|
26
|
+
? null
|
|
27
|
+
: computeSelectionBoundingBox(selectedFeatures, context.selectionScope.extensions);
|
|
28
|
+
if (bbox) {
|
|
29
|
+
const zoom = map.getZoom();
|
|
30
|
+
const getAdditionalHandles = getAdditionalResizeHandlesCallback(selectedFeatures, context.selectionScope);
|
|
31
|
+
const getAuxiliaryHandles = getAuxiliaryHandlesCallback(selectedFeatures, context.selectionScope);
|
|
32
|
+
const handleHit = hitTestHandles(event.point, selectedFeatures, transform, config, zoom, context.selectionScope, getAdditionalHandles, getAuxiliaryHandles);
|
|
33
|
+
if (handleHit) {
|
|
34
|
+
canvas.style.cursor = getCursorForHandle(handleHit);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// Selection-independent auxiliary handles (an extension implementation's focus, etc.). They
|
|
40
|
+
// appear regardless of whether there is a selection, so they are looked at after the selection
|
|
41
|
+
// handles and before the feature hit. They are not shown in a state where they cannot be
|
|
42
|
+
// grabbed (readOnly / interaction lock) (the cursor alone would be a lie suggesting it is
|
|
43
|
+
// possible).
|
|
44
|
+
if (!store.isReadOnly() && !store.isInteractionLocked()) {
|
|
45
|
+
const globalHit = hitTestGlobalAuxiliaryHandles(event.point, transform, config, map.getZoom(), getGlobalAuxiliaryHandlesCallback(context.selectionScope));
|
|
46
|
+
if (globalHit) {
|
|
47
|
+
canvas.style.cursor = getCursorForHandle(globalHit);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// Feature hit test (unified z traversal)
|
|
52
|
+
// When a dataset is in the foreground, the cursor becomes pointer only when it
|
|
53
|
+
// can fire click / hover (interactive). Showing pointer for a dataset that merely occludes
|
|
54
|
+
// would be a lie suggesting "it can be pressed".
|
|
55
|
+
const orderedFeatures = getDisplayFeatures(store);
|
|
56
|
+
const top = context.hitTestTopmost(event.point, { orderedFeatures });
|
|
57
|
+
canvas.style.cursor =
|
|
58
|
+
top === null || (top.kind === 'dataset' && !top.dataset.interactive) ? 'default' : 'pointer';
|
|
59
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auxiliary handle drag: delegated to the extension implementation that provides the handle
|
|
3
|
+
*/
|
|
4
|
+
import type { DragNormalizedEvent } from '../../../dispatcher/types.js';
|
|
5
|
+
import type { AuxiliaryHandleHit, AuxiliaryHandleProvider } from '../../../view/ui/auxiliary-handles.js';
|
|
6
|
+
import type { HandleHitResult } from '../../../view/ui/handle-test.js';
|
|
7
|
+
import type { DragScope } from './operation.js';
|
|
8
|
+
/**
|
|
9
|
+
* Drag state for an auxiliary handle (provided by an extension implementation)
|
|
10
|
+
*
|
|
11
|
+
* Holds the grabbed handle and the provider it is delegated to. The meaning of the coordinates
|
|
12
|
+
* lives on the provider side, so core merely forwards move / end and writes nothing to the Store.
|
|
13
|
+
*/
|
|
14
|
+
export interface AuxiliaryState {
|
|
15
|
+
provider: AuxiliaryHandleProvider;
|
|
16
|
+
hit: AuxiliaryHandleHit;
|
|
17
|
+
/** The last drag event forwarded (for cleanup on paths where dragend is not delivered) */
|
|
18
|
+
lastEvent: DragNormalizedEvent;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Check whether an auxiliary handle drag can be delegated to a provider
|
|
22
|
+
*
|
|
23
|
+
* When no provider is found, or when onHandleDragStart returns false, null is returned and the
|
|
24
|
+
* caller does not start a drag (it falls through to the normal handling).
|
|
25
|
+
*/
|
|
26
|
+
export declare function resolveAuxiliaryDrag(hitResult: HandleHitResult, event: DragNormalizedEvent, scope: DragScope): AuxiliaryDrag | null;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
|
|
2
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
|
+
/** @internal */
|
|
4
|
+
export class AuxiliaryDrag {
|
|
5
|
+
constructor(state) {
|
|
6
|
+
Object.defineProperty(this, "type", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
configurable: true,
|
|
9
|
+
writable: true,
|
|
10
|
+
value: 'auxiliary'
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(this, "state", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
configurable: true,
|
|
15
|
+
writable: true,
|
|
16
|
+
value: void 0
|
|
17
|
+
});
|
|
18
|
+
this.state = state;
|
|
19
|
+
}
|
|
20
|
+
update(event) {
|
|
21
|
+
if (!this.state)
|
|
22
|
+
return;
|
|
23
|
+
this.state.lastEvent = event;
|
|
24
|
+
this.state.provider.onHandleDragMove(event);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Tell the delegate that the auxiliary handle drag has ended
|
|
28
|
+
*
|
|
29
|
+
* On paths where no end event is delivered (when the mode side does not have an event), the
|
|
30
|
+
* last event that was forwarded is used instead. The delegate always receives end exactly once.
|
|
31
|
+
*/
|
|
32
|
+
finish(event) {
|
|
33
|
+
if (!this.state)
|
|
34
|
+
return;
|
|
35
|
+
const { provider, lastEvent } = this.state;
|
|
36
|
+
this.state = null;
|
|
37
|
+
provider.onHandleDragEnd(event ?? lastEvent);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Check whether an auxiliary handle drag can be delegated to a provider
|
|
42
|
+
*
|
|
43
|
+
* When no provider is found, or when onHandleDragStart returns false, null is returned and the
|
|
44
|
+
* caller does not start a drag (it falls through to the normal handling).
|
|
45
|
+
*/
|
|
46
|
+
export function resolveAuxiliaryDrag(hitResult, event, scope) {
|
|
47
|
+
const hit = hitResult.auxiliary;
|
|
48
|
+
if (!hit)
|
|
49
|
+
return null;
|
|
50
|
+
const provider = scope?.auxiliaryHandles.get(hit.providerId);
|
|
51
|
+
if (!provider)
|
|
52
|
+
return null;
|
|
53
|
+
if (!provider.onHandleDragStart(hit, event))
|
|
54
|
+
return null;
|
|
55
|
+
return new AuxiliaryDrag({ provider, hit, lastEvent: event });
|
|
56
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
|
|
2
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
|
+
/**
|
|
4
|
+
* Whether a feature still holds every field a drag wrote to it
|
|
5
|
+
*
|
|
6
|
+
* The values are plain data (coordinates and properties), so a structural comparison is
|
|
7
|
+
* enough. It runs only when a drag is aborted.
|
|
8
|
+
*/
|
|
9
|
+
function holdsFields(feature, fields) {
|
|
10
|
+
const source = feature;
|
|
11
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
12
|
+
if (JSON.stringify(source[key]) !== JSON.stringify(value))
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The intermediate writes of one drag
|
|
19
|
+
*
|
|
20
|
+
* @internal
|
|
21
|
+
*/
|
|
22
|
+
export class IntermediateWrites {
|
|
23
|
+
constructor() {
|
|
24
|
+
/**
|
|
25
|
+
* The last update applied to each feature touched during the drag (feature ID -> last diff
|
|
26
|
+
* written)
|
|
27
|
+
*
|
|
28
|
+
* Writes during a drag are issued as an intermediate state (isIntermediate), so the final
|
|
29
|
+
* state is rewritten as committed using the values recorded here in commit. It holds the diff
|
|
30
|
+
* as-is, including properties and not only coordinates, so scale / rotation from resize and
|
|
31
|
+
* rotate and radiusMeters from a radius change can all be committed through the same container.
|
|
32
|
+
*/
|
|
33
|
+
Object.defineProperty(this, "pending", {
|
|
34
|
+
enumerable: true,
|
|
35
|
+
configurable: true,
|
|
36
|
+
writable: true,
|
|
37
|
+
value: new Map()
|
|
38
|
+
});
|
|
39
|
+
/**
|
|
40
|
+
* The value each touched field had before the drag first wrote it (feature ID -> fields)
|
|
41
|
+
*
|
|
42
|
+
* An aborted drag writes these back, so the feature returns to the shape it had when the
|
|
43
|
+
* drag started, whether or not the Store applied the intermediate updates to the real data.
|
|
44
|
+
*/
|
|
45
|
+
Object.defineProperty(this, "origins", {
|
|
46
|
+
enumerable: true,
|
|
47
|
+
configurable: true,
|
|
48
|
+
writable: true,
|
|
49
|
+
value: new Map()
|
|
50
|
+
});
|
|
51
|
+
/** Every field the drag has written so far, merged (feature ID -> fields) */
|
|
52
|
+
Object.defineProperty(this, "written", {
|
|
53
|
+
enumerable: true,
|
|
54
|
+
configurable: true,
|
|
55
|
+
writable: true,
|
|
56
|
+
value: new Map()
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Write one intermediate update during the drag and record the last value for the commit
|
|
61
|
+
*
|
|
62
|
+
* During a drag, writes are issued as "an intermediate state partway through an editing
|
|
63
|
+
* operation", and the final state is committed together by commit when the drag ends.
|
|
64
|
+
* Deciding whether something is intermediate is core's responsibility; how that declaration
|
|
65
|
+
* is handled (persisted as-is, or routed through a temporary sharing path) is left to the
|
|
66
|
+
* Store implementation.
|
|
67
|
+
*/
|
|
68
|
+
write(store, id, updates) {
|
|
69
|
+
this.recordOrigin(store, id, updates);
|
|
70
|
+
store.updateFeature(id, updates, { isIntermediate: true });
|
|
71
|
+
this.pending.set(id, updates);
|
|
72
|
+
this.written.set(id, { ...this.written.get(id), ...updates });
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Remember the value of each field before the drag writes it for the first time
|
|
76
|
+
*/
|
|
77
|
+
recordOrigin(store, id, updates) {
|
|
78
|
+
const feature = store.getFeature(id);
|
|
79
|
+
if (!feature)
|
|
80
|
+
return;
|
|
81
|
+
const origin = this.origins.get(id) ?? {};
|
|
82
|
+
const target = origin;
|
|
83
|
+
const source = feature;
|
|
84
|
+
for (const key of Object.keys(updates)) {
|
|
85
|
+
if (key in target)
|
|
86
|
+
continue;
|
|
87
|
+
target[key] = structuredClone(source[key]);
|
|
88
|
+
}
|
|
89
|
+
this.origins.set(id, origin);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Abort the intermediate updates that never reached a commit, restoring the features
|
|
93
|
+
*
|
|
94
|
+
* On a reset that does not go through the end of the drag (a cancel, a mode switch during a
|
|
95
|
+
* drag, or an external state change applied from outside), the intermediate state
|
|
96
|
+
* ends without being committed. Each feature gets the fields it had when the drag started
|
|
97
|
+
* written back as a last intermediate update, and the discard is then announced with
|
|
98
|
+
* abortIntermediateUpdates. A store that applies intermediate updates to the real data
|
|
99
|
+
* (MemoryStore) is back at the start by the restore; one that holds them apart drops them on
|
|
100
|
+
* the discard. A feature that something else changed during the drag (a change from
|
|
101
|
+
* outside) no longer holds what the drag wrote, and is left as it is. Once committed (after
|
|
102
|
+
* commit) the record is empty, so nothing happens.
|
|
103
|
+
*/
|
|
104
|
+
discard(store) {
|
|
105
|
+
if (this.pending.size === 0) {
|
|
106
|
+
this.clearRecords();
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (store) {
|
|
110
|
+
const ids = [...this.pending.keys()];
|
|
111
|
+
store.transact(() => {
|
|
112
|
+
for (const id of ids) {
|
|
113
|
+
const origin = this.origins.get(id);
|
|
114
|
+
const written = this.written.get(id);
|
|
115
|
+
const feature = store.getFeature(id);
|
|
116
|
+
if (!origin || !written || !feature || !holdsFields(feature, written))
|
|
117
|
+
continue;
|
|
118
|
+
store.updateFeature(id, origin, { isIntermediate: true });
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
store.abortIntermediateUpdates?.(ids);
|
|
122
|
+
}
|
|
123
|
+
this.pending.clear();
|
|
124
|
+
this.clearRecords();
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Commit the intermediate updates made during the drag
|
|
128
|
+
*
|
|
129
|
+
* The last value of every feature that was touched (including features that followed along
|
|
130
|
+
* through a shared vertex) is rewritten as a committed update (no options), gathered into a
|
|
131
|
+
* single store.transact. Because it is notified as one StateChanges, a subscriber that records
|
|
132
|
+
* changes can treat this batch as a single step with its existing mechanism.
|
|
133
|
+
*
|
|
134
|
+
* The committed value is simply the last diff that was recorded. That way it does not depend
|
|
135
|
+
* on whether the intermediate updates during the drag were applied to the Store (some Store
|
|
136
|
+
* implementations do not apply intermediate updates to the real data).
|
|
137
|
+
*
|
|
138
|
+
* Only the features that still exist are committed. A feature can disappear during a drag (a
|
|
139
|
+
* deletion from outside, the public API, a plugin); its record is not committed but discarded like
|
|
140
|
+
* an aborted drag, so the commit never updates a missing feature and never lands halfway.
|
|
141
|
+
*/
|
|
142
|
+
commit(store) {
|
|
143
|
+
if (this.pending.size === 0)
|
|
144
|
+
return;
|
|
145
|
+
const vanished = [];
|
|
146
|
+
for (const id of this.pending.keys()) {
|
|
147
|
+
if (!store.getFeature(id))
|
|
148
|
+
vanished.push(id);
|
|
149
|
+
}
|
|
150
|
+
if (vanished.length > 0) {
|
|
151
|
+
store.abortIntermediateUpdates?.(vanished);
|
|
152
|
+
for (const id of vanished)
|
|
153
|
+
this.pending.delete(id);
|
|
154
|
+
}
|
|
155
|
+
if (this.pending.size > 0) {
|
|
156
|
+
store.transact(() => {
|
|
157
|
+
for (const [id, updates] of this.pending) {
|
|
158
|
+
store.updateFeature(id, updates);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
// A committed record is not a discard target (distinguished from the abort notification in
|
|
163
|
+
// reset)
|
|
164
|
+
this.pending.clear();
|
|
165
|
+
this.clearRecords();
|
|
166
|
+
}
|
|
167
|
+
clearRecords() {
|
|
168
|
+
this.origins.clear();
|
|
169
|
+
this.written.clear();
|
|
170
|
+
}
|
|
171
|
+
}
|