@sakuzu/maplibre-gl-draw 1.0.0 → 2.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 +1016 -2
- package/README.ja.md +39 -19
- package/README.md +41 -21
- package/dist/api/datasets.d.ts +258 -0
- package/dist/api/document.d.ts +66 -0
- package/dist/api/draw.d.ts +135 -0
- package/dist/api/draw.js +18 -0
- package/dist/api/drawing.d.ts +87 -0
- package/dist/api/errors.d.ts +35 -0
- package/dist/api/errors.js +35 -0
- package/dist/api/events.d.ts +306 -0
- package/dist/api/extension/context.d.ts +247 -0
- package/dist/api/extension/feature-type.d.ts +129 -0
- package/dist/api/extension/mode.d.ts +123 -0
- package/dist/api/extension/plugin.d.ts +51 -0
- package/dist/api/extension/plugin.js +3 -0
- package/dist/api/extension/provider.d.ts +119 -0
- package/dist/api/extension/provider.js +3 -0
- package/dist/api/extension/render.d.ts +176 -0
- package/dist/api/extension/render.js +3 -0
- package/dist/api/extension/store.d.ts +190 -0
- package/dist/api/extension/store.js +3 -0
- package/dist/api/extensions.d.ts +306 -0
- package/dist/api/extensions.js +3 -0
- package/dist/api/features.d.ts +188 -0
- package/dist/api/features.js +3 -0
- package/dist/api/groups.d.ts +111 -0
- package/dist/api/groups.js +3 -0
- package/dist/api/hidden.d.ts +45 -0
- package/dist/api/hidden.js +3 -0
- package/dist/api/impl/adapters.js +463 -0
- package/dist/api/impl/contexts.js +466 -0
- package/dist/api/impl/create-draw.js +124 -0
- package/dist/api/impl/datasets.js +404 -0
- package/dist/api/impl/destroy-guard.js +74 -0
- package/dist/api/impl/document.js +280 -0
- package/dist/api/impl/drawing.js +180 -0
- package/dist/api/impl/engine-context.d.ts +7 -0
- package/dist/api/{context.js → impl/engine-context.js} +49 -38
- package/dist/{maplibre-gl-draw.js → api/impl/engine.js} +145 -177
- package/dist/api/impl/events.js +422 -0
- package/dist/api/impl/extension-host.js +361 -0
- package/dist/api/impl/extensions.js +229 -0
- package/dist/api/impl/features.js +445 -0
- package/dist/api/impl/geometry/apply.d.ts +32 -0
- package/dist/api/{geometry → impl/geometry}/apply.js +10 -27
- package/dist/api/{geometry → impl/geometry}/buffer.d.ts +4 -3
- package/dist/api/{geometry → impl/geometry}/buffer.js +12 -23
- package/dist/api/{geometry → impl/geometry}/split.d.ts +4 -3
- package/dist/api/{geometry → impl/geometry}/split.js +10 -21
- package/dist/api/{geometry → impl/geometry}/targets.d.ts +2 -20
- package/dist/api/{geometry → impl/geometry}/targets.js +8 -35
- package/dist/api/impl/geometry/types.js +3 -0
- package/dist/api/impl/groups.d.ts +3 -0
- package/dist/api/impl/groups.js +268 -0
- package/dist/api/impl/hidden.js +60 -0
- package/dist/api/impl/import-export/constants.d.ts +22 -0
- package/dist/api/impl/import-export/constants.js +24 -0
- package/dist/api/{import-export → impl/import-export}/embedded-file.js +2 -2
- package/dist/api/{import-export → impl/import-export}/format-detection.d.ts +1 -1
- package/dist/api/{import-export → impl/import-export}/format-detection.js +2 -1
- package/dist/api/impl/import-export/geojson-export.d.ts +19 -0
- package/dist/api/{import-export → impl/import-export}/geojson-export.js +71 -104
- package/dist/api/{import-export → impl/import-export}/geojson-import.d.ts +11 -7
- package/dist/api/{import-export → impl/import-export}/geojson-import.js +139 -97
- package/dist/api/{import-export → impl/import-export}/geometry-validation.d.ts +14 -0
- package/dist/api/{import-export → impl/import-export}/geometry-validation.js +45 -0
- package/dist/api/impl/import-export/image-import.d.ts +16 -0
- package/dist/api/impl/import-export/image-import.js +73 -0
- package/dist/api/impl/import-export/legacy-image-style.d.ts +16 -0
- package/dist/api/impl/import-export/legacy-image-style.js +49 -0
- package/dist/api/impl/import-export/native-format.d.ts +14 -0
- package/dist/api/{import-export → impl/import-export}/native-format.js +32 -22
- package/dist/api/impl/import-export/native-upgrade.d.ts +8 -0
- package/dist/api/impl/import-export/native-upgrade.js +139 -0
- package/dist/api/{import-export → impl/import-export}/native-validation.d.ts +1 -1
- package/dist/api/{import-export → impl/import-export}/native-validation.js +15 -14
- package/dist/api/impl/import-export/style-validation.d.ts +24 -0
- package/dist/api/impl/import-export/style-validation.js +86 -0
- package/dist/api/impl/import-export/types.d.ts +52 -0
- package/dist/api/impl/import-export/types.js +3 -0
- package/dist/api/impl/input.js +180 -0
- package/dist/api/impl/layers.js +307 -0
- package/dist/api/impl/metadata.d.ts +1 -0
- package/dist/api/impl/metadata.js +22 -0
- package/dist/api/impl/options.d.ts +1 -0
- package/dist/api/impl/options.js +822 -0
- package/dist/api/impl/placement.d.ts +1 -0
- package/dist/api/impl/placement.js +138 -0
- package/dist/api/impl/render-context.d.ts +13 -0
- package/dist/api/impl/render-context.js +272 -0
- package/dist/api/impl/rows.d.ts +1 -0
- package/dist/api/impl/rows.js +46 -0
- package/dist/api/impl/selection.d.ts +1 -0
- package/dist/api/impl/selection.js +186 -0
- package/dist/api/impl/shared.d.ts +64 -0
- package/dist/api/impl/shared.js +178 -0
- package/dist/api/impl/validate-extension.d.ts +1 -0
- package/dist/api/impl/validate-extension.js +159 -0
- package/dist/api/layers.d.ts +130 -0
- package/dist/api/layers.js +3 -0
- package/dist/api/metadata.d.ts +18 -0
- package/dist/api/metadata.js +3 -0
- package/dist/api/model.d.ts +487 -0
- package/dist/api/model.js +47 -0
- package/dist/api/options.d.ts +466 -0
- package/dist/api/options.js +3 -0
- package/dist/api/selection.d.ts +94 -0
- package/dist/api/selection.js +3 -0
- package/dist/api/state.d.ts +155 -0
- package/dist/api/state.js +12 -0
- package/dist/{display → dataset}/chunk.d.ts +1 -1
- package/dist/{display → dataset}/chunk.js +4 -3
- package/dist/{display → dataset}/dataset.js +18 -21
- package/dist/dataset/interaction.d.ts +1 -0
- package/dist/{display → dataset}/interaction.js +18 -6
- package/dist/dataset/manager.d.ts +1 -0
- package/dist/dataset/provider.d.ts +1 -0
- package/dist/{display → dataset}/retained.d.ts +1 -1
- package/dist/{display → dataset}/retained.js +8 -7
- package/dist/dataset/source.d.ts +1 -0
- package/dist/{display → dataset}/source.js +17 -4
- package/dist/dataset/spatial.d.ts +1 -0
- package/dist/{display → dataset}/spatial.js +1 -1
- package/dist/dataset/style.d.ts +1 -0
- package/dist/{display → dataset}/style.js +1 -1
- package/dist/dataset/table-source.d.ts +1 -0
- package/dist/{display/columnar/source.js → dataset/table-source.js} +53 -25
- package/dist/{display → dataset}/thinning.d.ts +0 -10
- package/dist/{display → dataset}/thinning.js +3 -2
- package/dist/dataset/triangulation.d.ts +1 -0
- package/dist/{display → dataset}/triangulation.js +0 -0
- package/dist/{display → dataset}/types.d.ts +82 -121
- package/dist/dataset/types.js +61 -0
- package/dist/dispatcher/hit-test/box-strategies.js +13 -13
- package/dist/dispatcher/hit-test/box-strategy.d.ts +2 -15
- package/dist/dispatcher/hit-test/globe-shape.js +5 -4
- package/dist/dispatcher/hit-test/service.d.ts +17 -0
- package/dist/dispatcher/hit-test/service.js +80 -16
- package/dist/dispatcher/hit-test/strategies/base.d.ts +13 -19
- package/dist/dispatcher/hit-test/strategies/circle.js +3 -2
- package/dist/dispatcher/hit-test/strategies/image.js +6 -18
- package/dist/dispatcher/hit-test/strategies/line.d.ts +0 -6
- package/dist/dispatcher/hit-test/strategies/line.js +9 -2
- package/dist/dispatcher/hit-test/strategies/multi.d.ts +0 -8
- package/dist/dispatcher/hit-test/strategies/multi.js +17 -8
- package/dist/dispatcher/hit-test/strategies/point.d.ts +9 -7
- package/dist/dispatcher/hit-test/strategies/point.js +8 -4
- package/dist/dispatcher/hit-test/strategies/polygon.d.ts +0 -7
- package/dist/dispatcher/hit-test/strategies/polygon.js +11 -3
- package/dist/dispatcher/hit-test/topmost.d.ts +1 -1
- package/dist/dispatcher/input-router.js +152 -69
- package/dist/dispatcher/normalizer.js +6 -2
- package/dist/dispatcher/types.d.ts +6 -1
- package/dist/extension/feature-handler.d.ts +1 -182
- package/dist/extension/index.d.ts +4 -7
- package/dist/extension/renderers.d.ts +1 -208
- package/dist/geometry/angle.d.ts +0 -8
- package/dist/geometry/angle.js +0 -8
- package/dist/geometry/bbox.d.ts +4 -12
- package/dist/geometry/bbox.js +4 -12
- package/dist/geometry/boolean.d.ts +0 -51
- package/dist/geometry/boolean.js +0 -51
- package/dist/geometry/buffer.d.ts +0 -26
- package/dist/geometry/buffer.js +0 -26
- package/dist/geometry/circle.d.ts +0 -9
- package/dist/geometry/circle.js +0 -9
- package/dist/geometry/coords.d.ts +0 -16
- package/dist/geometry/coords.js +0 -16
- package/dist/geometry/distance.d.ts +0 -24
- package/dist/geometry/distance.js +0 -24
- package/dist/geometry/errors.d.ts +21 -36
- package/dist/geometry/errors.js +49 -29
- package/dist/geometry/geojson.d.ts +81 -0
- package/dist/geometry/geojson.js +164 -0
- package/dist/geometry/index.d.ts +38 -23
- package/dist/geometry/index.js +43 -31
- package/dist/geometry/measure.d.ts +0 -27
- package/dist/geometry/measure.js +0 -27
- package/dist/geometry/predicates.d.ts +0 -9
- package/dist/geometry/predicates.js +0 -9
- package/dist/geometry/public-bounds.d.ts +26 -0
- package/dist/geometry/public-bounds.js +30 -0
- package/dist/geometry/public-combine.d.ts +78 -0
- package/dist/geometry/public-combine.js +82 -0
- package/dist/geometry/public-create.d.ts +54 -0
- package/dist/geometry/public-create.js +70 -0
- package/dist/geometry/public-measure.d.ts +170 -0
- package/dist/geometry/public-measure.js +283 -0
- package/dist/geometry/public-predicates.d.ts +54 -0
- package/dist/geometry/public-predicates.js +144 -0
- package/dist/geometry/public-repair.d.ts +75 -0
- package/dist/geometry/public-repair.js +77 -0
- package/dist/geometry/simplify.d.ts +0 -7
- package/dist/geometry/simplify.js +0 -7
- package/dist/geometry/split.d.ts +0 -20
- package/dist/geometry/split.js +0 -20
- package/dist/geometry/units.d.ts +20 -12
- package/dist/geometry/units.js +20 -12
- package/dist/index.d.ts +52 -66
- package/dist/index.js +6 -18
- package/dist/messages.d.ts +7 -7
- package/dist/modes/draw/circle.js +83 -207
- package/dist/modes/draw/commit-layer.d.ts +5 -16
- package/dist/modes/draw/commit-layer.js +2 -13
- package/dist/modes/draw/freehand.js +108 -246
- package/dist/modes/draw/image.js +4 -2
- package/dist/modes/draw/index.d.ts +5 -5
- package/dist/modes/draw/index.js +5 -5
- package/dist/modes/draw/line.js +18 -354
- package/dist/modes/draw/point.js +29 -78
- package/dist/modes/draw/polygon.js +23 -368
- package/dist/modes/draw/trace-support.d.ts +43 -36
- package/dist/modes/draw/trace-support.js +95 -98
- package/dist/modes/draw/vertex-drawing.d.ts +1 -0
- package/dist/modes/draw/vertex-drawing.js +176 -0
- package/dist/modes/handler.d.ts +1 -285
- package/dist/modes/manager.d.ts +2 -2
- package/dist/modes/manager.js +3 -0
- package/dist/modes/select/box-selection.d.ts +3 -3
- package/dist/modes/select/box-selection.js +2 -1
- package/dist/modes/select/click-handler.d.ts +5 -5
- package/dist/modes/select/click-handler.js +22 -20
- package/dist/modes/select/cursor-handler.d.ts +2 -2
- package/dist/modes/select/drag/intermediate-writes.js +1 -1
- package/dist/modes/select/drag/move.js +3 -3
- package/dist/modes/select/drag/operation.d.ts +3 -3
- package/dist/modes/select/drag/radius.js +5 -4
- package/dist/modes/select/drag/transform.d.ts +2 -2
- package/dist/modes/select/drag/transform.js +11 -5
- package/dist/modes/select/drag/vertex.d.ts +2 -2
- package/dist/modes/select/drag/vertex.js +13 -8
- package/dist/modes/select/drag-handler.js +44 -25
- package/dist/modes/select/mode.js +17 -17
- package/dist/modes/select/shortcut-handler.d.ts +8 -8
- package/dist/modes/select/shortcut-handler.js +9 -7
- package/dist/operations/layer-operations.js +29 -168
- package/dist/operations/resize.d.ts +2 -2
- package/dist/operations/resize.js +5 -5
- package/dist/operations/rotate.js +5 -5
- package/dist/operations/selection-operations.d.ts +16 -1
- package/dist/operations/selection-operations.js +28 -13
- package/dist/operations/shared-vertex.js +4 -2
- package/dist/operations/trace-graph.d.ts +0 -18
- package/dist/operations/trace-graph.js +0 -18
- package/dist/operations/vertex.js +36 -35
- package/dist/shared/color.d.ts +1 -0
- package/dist/shared/color.js +245 -0
- package/dist/shared/config/constants.d.ts +1 -54
- package/dist/shared/config/constants.js +1 -58
- package/dist/shared/config/feature-style.d.ts +16 -13
- package/dist/shared/config/feature-style.js +9 -0
- package/dist/shared/config/rendering.d.ts +3 -3
- package/dist/shared/config/selection-highlight.d.ts +0 -15
- package/dist/shared/config/selection-highlight.js +4 -7
- package/dist/shared/config/selection.d.ts +2 -32
- package/dist/shared/config/selection.js +0 -18
- package/dist/shared/config/topology.d.ts +2 -2
- package/dist/shared/config/trace.d.ts +4 -4
- package/dist/shared/math/angle.d.ts +1 -1
- package/dist/shared/math/angle.js +1 -1
- package/dist/shared/math/circle.d.ts +1 -1
- package/dist/shared/math/circle.js +1 -1
- package/dist/shared/math/distance.d.ts +2 -1
- package/dist/shared/math/distance.js +3 -2
- package/dist/shared/math/index.d.ts +1 -1
- package/dist/shared/math/index.js +1 -1
- package/dist/shared/math/transform.d.ts +23 -0
- package/dist/shared/math/transform.js +47 -28
- package/dist/shared/properties.d.ts +18 -0
- package/dist/shared/properties.js +129 -0
- package/dist/shared/types/events.d.ts +15 -7
- package/dist/shared/types/model.d.ts +109 -159
- package/dist/shared/types/style.d.ts +1 -1
- package/dist/shared/utils/color.d.ts +2 -36
- package/dist/shared/utils/color.js +13 -70
- package/dist/shared/utils/coordinates.d.ts +30 -4
- package/dist/shared/utils/coordinates.js +56 -10
- package/dist/shared/utils/event-emitter.d.ts +1 -262
- package/dist/shared/utils/event-emitter.js +4 -3
- package/dist/shared/utils/feature-bbox.js +8 -7
- package/dist/shared/utils/feature-segments.js +5 -4
- package/dist/shared/utils/image.d.ts +0 -4
- package/dist/shared/utils/image.js +0 -6
- package/dist/shared/utils/name-generator.d.ts +14 -20
- package/dist/shared/utils/name-generator.js +20 -3
- package/dist/shared/utils/pixel-ratio.d.ts +9 -3
- package/dist/shared/utils/pixel-ratio.js +13 -4
- package/dist/shared/utils/property.d.ts +7 -50
- package/dist/shared/utils/property.js +22 -87
- package/dist/snapping/custom-targets.js +21 -4
- package/dist/snapping/indicator.js +20 -11
- package/dist/snapping/providers/display.d.ts +6 -1
- package/dist/snapping/providers/display.js +2 -1
- package/dist/snapping/providers/guide.d.ts +3 -43
- package/dist/snapping/providers/guide.js +1 -44
- package/dist/snapping/providers/intersection.js +1 -1
- package/dist/snapping/providers/store.js +3 -3
- package/dist/snapping/service.js +18 -7
- package/dist/snapping/types.d.ts +9 -35
- package/dist/store/draw-store.js +233 -142
- package/dist/store/local-visibility.d.ts +11 -6
- package/dist/store/local-visibility.js +38 -7
- package/dist/store/lock.d.ts +0 -6
- package/dist/store/lock.js +0 -6
- package/dist/store/memory/change-bus.d.ts +3 -3
- package/dist/store/memory/change-bus.js +12 -0
- package/dist/store/memory/file-store.d.ts +2 -2
- package/dist/store/memory/ui-state.d.ts +1 -51
- package/dist/store/memory/ui-state.js +122 -134
- package/dist/store/memory.d.ts +1 -8
- package/dist/store/memory.js +249 -45
- package/dist/store/ordering.d.ts +9 -0
- package/dist/store/ordering.js +17 -0
- package/dist/store/spatial/spatial-index.d.ts +1 -1
- package/dist/store/spatial/spatial-index.js +1 -1
- package/dist/store/spatial/store-spatial-index.d.ts +3 -1
- package/dist/store/spatial/store-spatial-index.js +9 -3
- package/dist/store/store.d.ts +66 -107
- package/dist/store/types.d.ts +1 -1
- package/dist/store/writable-layer.d.ts +1 -1
- package/dist/store/writable-layer.js +2 -2
- package/dist/table/builder.d.ts +83 -0
- package/dist/table/builder.js +381 -0
- package/dist/table/index.d.ts +37 -0
- package/dist/table/index.js +5 -0
- package/dist/table/packed-rtree.d.ts +1 -0
- package/dist/{display → table}/packed-rtree.js +1 -1
- package/dist/table/partition.d.ts +1 -0
- package/dist/{display → table}/partition.js +3 -3
- package/dist/table/prepare.d.ts +44 -0
- package/dist/table/prepare.js +136 -0
- package/dist/table/table.d.ts +1 -0
- package/dist/{display/columnar → table}/table.js +29 -25
- package/dist/{display/columnar → table}/types.d.ts +68 -72
- package/dist/table/types.js +3 -0
- package/dist/view/coordinator.js +4 -3
- package/dist/view/feature-companion.d.ts +13 -7
- package/dist/view/feature-companion.js +11 -3
- package/dist/view/globe-subdivision.js +3 -3
- package/dist/view/layer/attach.d.ts +1 -1
- package/dist/view/layer/attach.js +1 -1
- package/dist/view/layer/custom-layer.js +40 -11
- package/dist/view/layer/display-list.js +2 -1
- package/dist/view/layer/drape-planner.d.ts +2 -2
- package/dist/view/layer/frame-render.d.ts +3 -3
- package/dist/view/layer/frame-render.js +7 -2
- package/dist/view/layer/frame-state.d.ts +6 -6
- package/dist/view/layer/index.d.ts +2 -2
- package/dist/view/layer/index.js +1 -1
- package/dist/view/layer/render.d.ts +4 -4
- package/dist/view/layer/render.js +3 -8
- package/dist/view/layer/renderers.d.ts +2 -2
- package/dist/view/layer/renderers.js +1 -1
- package/dist/view/layer/slot-manager.d.ts +2 -2
- package/dist/view/layer/slot-manager.js +4 -4
- package/dist/view/layer/slots.d.ts +2 -2
- package/dist/view/layer/slots.js +1 -1
- package/dist/view/layer/store-retained-bbox.js +3 -2
- package/dist/view/layer/store-retained-classify.d.ts +5 -7
- package/dist/view/layer/store-retained-classify.js +19 -7
- package/dist/view/layer/store-retained-collect.js +8 -7
- package/dist/view/layer/store-retained-coord-patch.d.ts +0 -8
- package/dist/view/layer/store-retained-coord-patch.js +13 -4
- package/dist/view/layer/store-retained-immediate.d.ts +3 -3
- package/dist/view/layer/store-retained-immediate.js +3 -8
- package/dist/view/layer/store-retained-invalidation.d.ts +2 -2
- package/dist/view/layer/store-retained.d.ts +2 -2
- package/dist/view/layer/store-retained.js +1 -1
- package/dist/view/renderers/batch-manager.js +8 -7
- package/dist/view/renderers/drawer.js +21 -15
- package/dist/view/renderers/image.js +13 -39
- package/dist/view/renderers/line/line-types.d.ts +3 -3
- package/dist/view/renderers/line/sdf-line.js +3 -1
- package/dist/view/renderers/point/billboard-depth.js +1 -1
- package/dist/view/renderers/point/point-instance.js +1 -1
- package/dist/view/renderers/point/point-shape.js +2 -2
- package/dist/view/renderers/point/point-style.js +48 -4
- package/dist/view/renderers/polygon/batch.js +1 -2
- package/dist/view/renderers/polygon/fill.js +3 -1
- package/dist/view/renderers/polygon/sdf-polygon.js +2 -3
- package/dist/view/renderers/polygon/triangulator.d.ts +1 -1
- package/dist/view/renderers/stroke.js +3 -1
- package/dist/view/shaders/helpers.d.ts +2 -42
- package/dist/view/shaders/helpers.js +0 -6
- package/dist/view/shaders/projection.d.ts +15 -7
- package/dist/view/shaders/projection.js +23 -6
- package/dist/view/shaders/quad.d.ts +16 -12
- package/dist/view/shaders/quad.js +34 -13
- package/dist/view/style-rule.d.ts +5 -42
- package/dist/view/style-rule.js +20 -44
- package/dist/view/terrain/binding.d.ts +1 -0
- package/dist/view/terrain/binding.js +29 -0
- package/dist/view/terrain/context.d.ts +3 -4
- package/dist/view/terrain/context.js +4 -5
- package/dist/view/terrain/drape/geometry.js +1 -1
- package/dist/view/terrain/drape/pass.d.ts +1 -1
- package/dist/view/terrain/drape/pass.js +8 -7
- package/dist/view/terrain/polygon.d.ts +9 -5
- package/dist/view/terrain/polygon.js +16 -2
- package/dist/view/terrain/state.d.ts +1 -1
- package/dist/view/terrain/state.js +1 -1
- package/dist/view/terrain/tessellation.d.ts +2 -2
- package/dist/view/terrain/tessellation.js +1 -1
- package/dist/view/ui/auxiliary-handles.d.ts +6 -29
- package/dist/view/ui/bounds.js +8 -12
- package/dist/view/ui/handle-test.js +2 -2
- package/dist/view/ui/handle-thinning.js +17 -17
- package/dist/view/ui/handles.js +21 -13
- package/dist/view/ui/helper.d.ts +1 -1
- package/dist/view/ui/helper.js +1 -1
- package/dist/view/ui/index.d.ts +1 -1
- package/dist/view/ui/selection-scope.js +4 -2
- package/dist/view/ui/selection-ui/bounding-box.js +6 -6
- package/dist/view/ui/selection-ui/extension-registry.d.ts +31 -20
- package/dist/view/ui/selection-ui/extension-registry.js +70 -7
- package/dist/view/ui/selection-ui/index.d.ts +2 -2
- package/dist/view/ui/selection-ui/index.js +1 -1
- package/dist/view/ui/selection-ui/renderer.js +15 -38
- package/dist/view/ui/selection-ui/types.d.ts +17 -2
- package/dist/view/ui/selection-ui-drawer.d.ts +8 -0
- package/dist/view/ui/selection-ui-drawer.js +63 -2
- package/dist/view/ui/tentative.js +1 -1
- package/dist/webgl/index.d.ts +65 -0
- package/dist/webgl/index.js +62 -0
- package/package.json +20 -9
- package/dist/api/api.d.ts +0 -1259
- package/dist/api/api.js +0 -86
- package/dist/api/context.d.ts +0 -173
- package/dist/api/display-api.js +0 -23
- package/dist/api/event-api.d.ts +0 -13
- package/dist/api/event-api.js +0 -17
- package/dist/api/extension-api.d.ts +0 -46
- package/dist/api/extension-api.js +0 -85
- package/dist/api/feature-api.d.ts +0 -11
- package/dist/api/feature-api.js +0 -101
- package/dist/api/geometry/apply.d.ts +0 -51
- package/dist/api/geometry/boolean.d.ts +0 -28
- package/dist/api/geometry/boolean.js +0 -65
- package/dist/api/geometry/types.d.ts +0 -31
- package/dist/api/geometry-operations.d.ts +0 -162
- package/dist/api/geometry-operations.js +0 -94
- package/dist/api/group-api.d.ts +0 -10
- package/dist/api/group-api.js +0 -78
- package/dist/api/import-export/constants.d.ts +0 -29
- package/dist/api/import-export/constants.js +0 -40
- package/dist/api/import-export/file-name.d.ts +0 -10
- package/dist/api/import-export/file-name.js +0 -20
- package/dist/api/import-export/geojson-export.d.ts +0 -19
- package/dist/api/import-export/image-import.d.ts +0 -12
- package/dist/api/import-export/image-import.js +0 -53
- package/dist/api/import-export/index.d.ts +0 -9
- package/dist/api/import-export/index.js +0 -107
- package/dist/api/import-export/native-format.d.ts +0 -15
- package/dist/api/import-export/style-validation.d.ts +0 -27
- package/dist/api/import-export/style-validation.js +0 -49
- package/dist/api/import-export/types.d.ts +0 -26
- package/dist/api/index.d.ts +0 -15
- package/dist/api/index.js +0 -3
- package/dist/api/input-api.d.ts +0 -158
- package/dist/api/input-api.js +0 -144
- package/dist/api/instance-api.d.ts +0 -38
- package/dist/api/instance-api.js +0 -136
- package/dist/api/layer-api.d.ts +0 -12
- package/dist/api/layer-api.js +0 -62
- package/dist/api/selection-api.d.ts +0 -7
- package/dist/api/selection-api.js +0 -78
- package/dist/api/snapping-api.d.ts +0 -125
- package/dist/api/snapping-api.js +0 -50
- package/dist/api/topology-api.d.ts +0 -30
- package/dist/api/topology-api.js +0 -16
- package/dist/api/tracing-api.d.ts +0 -31
- package/dist/api/tracing-api.js +0 -16
- package/dist/dispatcher/hit-test/index.d.ts +0 -14
- package/dist/dispatcher/hit-test/index.js +0 -9
- package/dist/dispatcher/index.d.ts +0 -15
- package/dist/dispatcher/index.js +0 -3
- package/dist/display/columnar/index.d.ts +0 -12
- package/dist/display/columnar/index.js +0 -13
- package/dist/display/columnar/prepare.d.ts +0 -42
- package/dist/display/columnar/prepare.js +0 -116
- package/dist/display/index.d.ts +0 -13
- package/dist/display/types.js +0 -43
- package/dist/maplibre-gl-draw.d.ts +0 -47
- package/dist/modes/cursor.js +0 -72
- package/dist/modes/index.d.ts +0 -7
- package/dist/operations/index.d.ts +0 -9
- package/dist/operations/index.js +0 -3
- package/dist/plugins/index.d.ts +0 -10
- package/dist/plugins/mutation-hooks.d.ts +0 -28
- package/dist/plugins/mutation-hooks.js +0 -84
- package/dist/plugins/plugin-context.js +0 -367
- package/dist/plugins/plugin-manager.d.ts +0 -103
- package/dist/plugins/plugin-manager.js +0 -316
- package/dist/plugins/plugin.d.ts +0 -529
- package/dist/shared/config/index.d.ts +0 -17
- package/dist/shared/config/index.js +0 -8
- package/dist/shared/utils/index.d.ts +0 -15
- package/dist/shared/utils/index.js +0 -24
- package/dist/snapping/index.d.ts +0 -14
- package/dist/snapping/index.js +0 -4
- package/dist/store/change-merger.js +0 -102
- package/dist/store/event-bridge.js +0 -161
- package/dist/store/index.d.ts +0 -12
- package/dist/store/index.js +0 -4
- package/dist/view/index.d.ts +0 -47
- package/dist/view/index.js +0 -20
- /package/dist/api/{geometry/types.js → datasets.js} +0 -0
- /package/dist/api/{import-export/types.js → document.js} +0 -0
- /package/dist/{display/columnar/types.js → api/drawing.js} +0 -0
- /package/dist/{display/index.js → api/events.js} +0 -0
- /package/dist/{modes/index.js → api/extension/context.js} +0 -0
- /package/dist/{plugins/index.js → api/extension/feature-type.js} +0 -0
- /package/dist/{plugins/plugin.js → api/extension/mode.js} +0 -0
- /package/dist/api/{display-api.d.ts → impl/adapters.d.ts} +0 -0
- /package/dist/{display/columnar/source.d.ts → api/impl/contexts.d.ts} +0 -0
- /package/dist/{display/columnar/table.d.ts → api/impl/create-draw.d.ts} +0 -0
- /package/dist/{display/interaction.d.ts → api/impl/datasets.d.ts} +0 -0
- /package/dist/{display/manager.d.ts → api/impl/destroy-guard.d.ts} +0 -0
- /package/dist/{display/packed-rtree.d.ts → api/impl/document.d.ts} +0 -0
- /package/dist/{display/partition.d.ts → api/impl/drawing.d.ts} +0 -0
- /package/dist/{display/provider.d.ts → api/impl/engine.d.ts} +0 -0
- /package/dist/{display/source.d.ts → api/impl/events.d.ts} +0 -0
- /package/dist/{display/spatial.d.ts → api/impl/extension-host.d.ts} +0 -0
- /package/dist/{display/style.d.ts → api/impl/extensions.d.ts} +0 -0
- /package/dist/{display/triangulation.d.ts → api/impl/features.d.ts} +0 -0
- /package/dist/{modes/cursor.d.ts → api/impl/geometry/types.d.ts} +0 -0
- /package/dist/{plugins/plugin-context.d.ts → api/impl/hidden.d.ts} +0 -0
- /package/dist/api/{import-export → impl/import-export}/embedded-file.d.ts +0 -0
- /package/dist/api/{import-export → impl/import-export}/own-property.d.ts +0 -0
- /package/dist/api/{import-export → impl/import-export}/own-property.js +0 -0
- /package/dist/{store/change-merger.d.ts → api/impl/input.d.ts} +0 -0
- /package/dist/{store/event-bridge.d.ts → api/impl/layers.d.ts} +0 -0
- /package/dist/{display → dataset}/chunk-set.d.ts +0 -0
- /package/dist/{display → dataset}/chunk-set.js +0 -0
- /package/dist/{display → dataset}/dataset.d.ts +0 -0
- /package/dist/{display → dataset}/manager.js +0 -0
- /package/dist/{display → dataset}/provider.js +0 -0
- /package/dist/{display → dataset}/selection.d.ts +0 -0
- /package/dist/{display → dataset}/selection.js +0 -0
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
// SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
|
|
2
2
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
*/
|
|
7
|
-
import { createId } from '../../shared/utils/id.js';
|
|
8
|
-
import { GEOJSON_PREFIX, LIBRARY_PROPERTIES } from './constants.js';
|
|
3
|
+
import { DRAW_PROPERTY_NAMES, DRAW_PROPERTY_PREFIX, drawPropertyKey, hasDrawProperty, setDrawProperty, } from '../../../shared/properties.js';
|
|
4
|
+
import { createId } from '../../../shared/utils/id.js';
|
|
5
|
+
import { DrawError } from '../../errors.js';
|
|
9
6
|
import { normalizeEmbeddedFile } from './embedded-file.js';
|
|
10
7
|
import { COORDINATE_DEPTH, describeCoordinateProblem } from './geometry-validation.js';
|
|
8
|
+
import { foldLegacyImageStyle } from './legacy-image-style.js';
|
|
11
9
|
import { setOwnProperty } from './own-property.js';
|
|
12
|
-
import {
|
|
10
|
+
import { isCssColor, sanitizeFeatureStyle } from './style-validation.js';
|
|
13
11
|
/**
|
|
14
12
|
* Converts a single geometry (Point/LineString/Polygon) into the Feature format
|
|
15
13
|
*/
|
|
@@ -28,7 +26,7 @@ function convertSingleGeometry(geometry, meta, userProperties, featureType, file
|
|
|
28
26
|
case 'Point': {
|
|
29
27
|
const type = resolveFeatureType('Point', featureType);
|
|
30
28
|
return {
|
|
31
|
-
feature: { ...base, type,
|
|
29
|
+
feature: { ...base, type, geometry },
|
|
32
30
|
// The embedded image belongs only to a feature that really is an Image
|
|
33
31
|
fileData: type === 'Image' ? fileData : undefined,
|
|
34
32
|
};
|
|
@@ -39,19 +37,16 @@ function convertSingleGeometry(geometry, meta, userProperties, featureType, file
|
|
|
39
37
|
// (this pairs with the default branch on export).
|
|
40
38
|
const type = resolveFeatureType('LineString', featureType);
|
|
41
39
|
return {
|
|
42
|
-
feature: {
|
|
43
|
-
...base,
|
|
44
|
-
type,
|
|
45
|
-
coordinates: geometry.coordinates,
|
|
46
|
-
},
|
|
40
|
+
feature: { ...base, type, geometry },
|
|
47
41
|
};
|
|
48
42
|
}
|
|
49
43
|
case 'Polygon':
|
|
44
|
+
// A custom type whose geometry is an area comes back from its marker as the others do
|
|
50
45
|
return {
|
|
51
46
|
feature: {
|
|
52
47
|
...base,
|
|
53
|
-
type: 'Polygon',
|
|
54
|
-
|
|
48
|
+
type: resolveFeatureType('Polygon', featureType),
|
|
49
|
+
geometry,
|
|
55
50
|
},
|
|
56
51
|
};
|
|
57
52
|
default:
|
|
@@ -64,7 +59,7 @@ function convertSingleGeometry(geometry, meta, userProperties, featureType, file
|
|
|
64
59
|
* The parts are kept as they are instead of being split, so that properties are not
|
|
65
60
|
* duplicated.
|
|
66
61
|
*/
|
|
67
|
-
function convertMultiGeometry(geometry, meta, userProperties) {
|
|
62
|
+
function convertMultiGeometry(geometry, meta, userProperties, featureType) {
|
|
68
63
|
if (geometry.coordinates.length === 0)
|
|
69
64
|
return null;
|
|
70
65
|
return [
|
|
@@ -77,8 +72,8 @@ function convertMultiGeometry(geometry, meta, userProperties) {
|
|
|
77
72
|
style: meta.style,
|
|
78
73
|
locked: meta.locked,
|
|
79
74
|
visible: meta.visible,
|
|
80
|
-
type: geometry.type,
|
|
81
|
-
|
|
75
|
+
type: resolveFeatureType(geometry.type, featureType),
|
|
76
|
+
geometry,
|
|
82
77
|
},
|
|
83
78
|
},
|
|
84
79
|
];
|
|
@@ -164,7 +159,7 @@ function convertGeometryCollection(geometry, meta, userProperties, generateFeatu
|
|
|
164
159
|
locked: meta.locked,
|
|
165
160
|
visible: meta.visible,
|
|
166
161
|
type,
|
|
167
|
-
coordinates,
|
|
162
|
+
geometry: { type, coordinates },
|
|
168
163
|
},
|
|
169
164
|
});
|
|
170
165
|
};
|
|
@@ -187,14 +182,15 @@ const GEOMETRY_TYPE_NAMES = new Set([
|
|
|
187
182
|
'geometrycollection',
|
|
188
183
|
]);
|
|
189
184
|
/**
|
|
190
|
-
* Resolves the feature type of a
|
|
185
|
+
* Resolves the feature type of a geometry from the featureType marker
|
|
191
186
|
*
|
|
192
187
|
* The marker restores a type that GeoJSON has no geometry for (Image, Circle, Freehand and
|
|
193
|
-
* custom types). The export writes the type name as it is, and the
|
|
194
|
-
*
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
*
|
|
188
|
+
* custom types, whatever their geometry). The export writes the type name as it is, and the
|
|
189
|
+
* marker is read as that exact name: it wins over the kind of the geometry. It is used only
|
|
190
|
+
* when it is a non-empty string, does not name a GeoJSON geometry type (in any letter case),
|
|
191
|
+
* and does not name a built-in type whose coordinates have another shape. Anything else is
|
|
192
|
+
* ignored and the geometry type is kept, so the marker can never pair a built-in type with
|
|
193
|
+
* coordinates of another shape.
|
|
198
194
|
*/
|
|
199
195
|
function resolveFeatureType(geometryType, marker) {
|
|
200
196
|
if (typeof marker !== 'string' || marker === '')
|
|
@@ -202,9 +198,13 @@ function resolveFeatureType(geometryType, marker) {
|
|
|
202
198
|
if (GEOMETRY_TYPE_NAMES.has(marker.toLowerCase()))
|
|
203
199
|
return geometryType;
|
|
204
200
|
const expectedDepth = COORDINATE_DEPTH[marker];
|
|
205
|
-
const actualDepth = geometryType
|
|
201
|
+
const actualDepth = COORDINATE_DEPTH[geometryType];
|
|
206
202
|
return expectedDepth === undefined || expectedDepth === actualDepth ? marker : geometryType;
|
|
207
203
|
}
|
|
204
|
+
/** The keys of `properties` that hold the values of this library */
|
|
205
|
+
const LIBRARY_KEYS = new Set(DRAW_PROPERTY_NAMES.map((name) => drawPropertyKey(name)));
|
|
206
|
+
/** The values of a Circle that an earlier export wrote without the prefix */
|
|
207
|
+
const LEGACY_CIRCLE_PROPERTIES = ['radiusMeters', 'radiusHandleAngle'];
|
|
208
208
|
/** The geometry types the import converts */
|
|
209
209
|
const SUPPORTED_GEOMETRY_TYPES = new Set([
|
|
210
210
|
'Point',
|
|
@@ -286,7 +286,7 @@ function simplestyleToFeatureStyle(properties) {
|
|
|
286
286
|
let found = false;
|
|
287
287
|
const copyString = (key, target) => {
|
|
288
288
|
const value = properties[key];
|
|
289
|
-
if (
|
|
289
|
+
if (isCssColor(value)) {
|
|
290
290
|
style[target] = value;
|
|
291
291
|
found = true;
|
|
292
292
|
}
|
|
@@ -333,7 +333,7 @@ export function convertGeoJSONToFeature(geoFeature, layerId, generateFeatureId,
|
|
|
333
333
|
// form, and anything else gets a new id. The prefixed property takes precedence, then the
|
|
334
334
|
// standard id member of the Feature. Whether it collides with existing data is resolved by
|
|
335
335
|
// the caller, which knows the store.
|
|
336
|
-
const prefixedId = properties?.[`${
|
|
336
|
+
const prefixedId = properties?.[`${DRAW_PROPERTY_PREFIX}id`];
|
|
337
337
|
const rawId = prefixedId === undefined || prefixedId === null || prefixedId === ''
|
|
338
338
|
? geoFeature.id
|
|
339
339
|
: prefixedId;
|
|
@@ -342,54 +342,65 @@ export function convertGeoJSONToFeature(geoFeature, layerId, generateFeatureId,
|
|
|
342
342
|
: typeof rawId === 'number' && Number.isFinite(rawId)
|
|
343
343
|
? String(rawId)
|
|
344
344
|
: generateFeatureId();
|
|
345
|
-
const rawLayerId = properties?.[`${
|
|
345
|
+
const rawLayerId = properties?.[`${DRAW_PROPERTY_PREFIX}layerId`];
|
|
346
346
|
const featureLayerId = typeof rawLayerId === 'string' && rawLayerId !== '' ? rawLayerId : layerId;
|
|
347
|
-
const rawGroupId = properties?.[`${
|
|
347
|
+
const rawGroupId = properties?.[`${DRAW_PROPERTY_PREFIX}groupId`];
|
|
348
348
|
const groupId = typeof rawGroupId === 'string' && rawGroupId !== '' ? rawGroupId : undefined;
|
|
349
349
|
// The round-trip style key takes precedence; only when it is absent is the style built
|
|
350
350
|
// from simplestyle-spec (they are not merged). Either way the keys are validated.
|
|
351
|
-
const roundTripStyle = properties?.[`${
|
|
352
|
-
const style = roundTripStyle !== undefined && roundTripStyle !== null
|
|
351
|
+
const roundTripStyle = properties?.[`${DRAW_PROPERTY_PREFIX}style`];
|
|
352
|
+
const style = (roundTripStyle !== undefined && roundTripStyle !== null
|
|
353
353
|
? sanitizeFeatureStyle(roundTripStyle)
|
|
354
|
-
: simplestyleToFeatureStyle(properties);
|
|
355
|
-
const featureType = properties?.[`${
|
|
354
|
+
: simplestyleToFeatureStyle(properties)) ?? {};
|
|
355
|
+
const featureType = properties?.[`${DRAW_PROPERTY_PREFIX}featureType`];
|
|
356
356
|
// visible is hidden only when it is explicitly false, and locked is treated as locked
|
|
357
357
|
// only when it is explicitly true
|
|
358
|
-
const visible = properties?.[`${
|
|
359
|
-
const locked = properties?.[`${
|
|
358
|
+
const visible = properties?.[`${DRAW_PROPERTY_PREFIX}visible`] !== false;
|
|
359
|
+
const locked = properties?.[`${DRAW_PROPERTY_PREFIX}locked`] === true;
|
|
360
360
|
// Extract the embedded image data. It is taken only for a single point that really is an
|
|
361
361
|
// Image.
|
|
362
|
-
const imageData = properties?.[`${
|
|
363
|
-
const imageMimeType = properties?.[`${
|
|
362
|
+
const imageData = properties?.[`${DRAW_PROPERTY_PREFIX}imageData`];
|
|
363
|
+
const imageMimeType = properties?.[`${DRAW_PROPERTY_PREFIX}imageMimeType`];
|
|
364
364
|
const embedsImage = Boolean(imageData && imageMimeType) &&
|
|
365
365
|
geometry.type === 'Point' &&
|
|
366
366
|
resolveFeatureType('Point', featureType) === 'Image';
|
|
367
367
|
// Extract the properties
|
|
368
368
|
// - without a prefix: added as is as a user-defined property
|
|
369
|
-
// - with a prefix and one of this library's own
|
|
369
|
+
// - with a prefix and one of this library's own values: added as is
|
|
370
370
|
// - any other prefixed key (id, layerId, style, visible, locked and so on): excluded
|
|
371
371
|
// (they are handled separately)
|
|
372
372
|
// Keys are defined as own properties so that a `__proto__` key stays an ordinary key.
|
|
373
373
|
const userProperties = {};
|
|
374
374
|
if (properties) {
|
|
375
375
|
for (const [key, value] of Object.entries(properties)) {
|
|
376
|
-
if (key.startsWith(
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
setOwnProperty(userProperties, keyWithoutPrefix, value);
|
|
383
|
-
}
|
|
376
|
+
if (key.startsWith(DRAW_PROPERTY_PREFIX)) {
|
|
377
|
+
// When there is image data, imageFileId is replaced with a new ID, so it is not
|
|
378
|
+
// added here. Anything else that is not a value of this library (id, layerId, style,
|
|
379
|
+
// featureType, visible, locked, imageData and so on) is excluded
|
|
380
|
+
if (LIBRARY_KEYS.has(key) && (key !== drawPropertyKey('imageFileId') || !embedsImage)) {
|
|
381
|
+
setOwnProperty(userProperties, key, value);
|
|
384
382
|
}
|
|
385
|
-
// Anything else (id, layerId, style, featureType, visible, locked, imageData and
|
|
386
|
-
// so on) is excluded
|
|
387
383
|
}
|
|
388
384
|
else {
|
|
389
385
|
setOwnProperty(userProperties, key, value);
|
|
390
386
|
}
|
|
391
387
|
}
|
|
392
388
|
}
|
|
389
|
+
// An earlier export wrote the radius of a Circle and the direction of its handle without
|
|
390
|
+
// the prefix; they are read as the values of this library when the prefixed ones are absent
|
|
391
|
+
if (geometry.type === 'Point' && resolveFeatureType('Point', featureType) === 'Circle') {
|
|
392
|
+
for (const name of LEGACY_CIRCLE_PROPERTIES) {
|
|
393
|
+
if (userProperties[name] !== undefined && !hasDrawProperty(userProperties, name)) {
|
|
394
|
+
setOwnProperty(userProperties, drawPropertyKey(name), userProperties[name]);
|
|
395
|
+
delete userProperties[name];
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
// The style of an Image written by an earlier export can carry its size, a rotation and an
|
|
400
|
+
// opacity of its own; they are read as the values of this library and imageOpacity
|
|
401
|
+
if (geometry.type === 'Point' && resolveFeatureType('Point', featureType) === 'Image') {
|
|
402
|
+
foldLegacyImageStyle(userProperties, style);
|
|
403
|
+
}
|
|
393
404
|
// When there is image data on a single Image point, create the FileData and set a new
|
|
394
405
|
// imageFileId
|
|
395
406
|
let fileData;
|
|
@@ -400,7 +411,7 @@ export function convertGeoJSONToFeature(geoFeature, layerId, generateFeatureId,
|
|
|
400
411
|
mimeType: imageMimeType,
|
|
401
412
|
dataURL: imageData,
|
|
402
413
|
};
|
|
403
|
-
userProperties
|
|
414
|
+
setDrawProperty(userProperties, 'imageFileId', newFileId);
|
|
404
415
|
}
|
|
405
416
|
const meta = {
|
|
406
417
|
id,
|
|
@@ -420,17 +431,17 @@ export function convertGeoJSONToFeature(geoFeature, layerId, generateFeatureId,
|
|
|
420
431
|
}
|
|
421
432
|
case 'MultiPoint':
|
|
422
433
|
if (!flattenMulti) {
|
|
423
|
-
return convertMultiGeometry(geometry, meta, userProperties);
|
|
434
|
+
return convertMultiGeometry(geometry, meta, userProperties, featureType);
|
|
424
435
|
}
|
|
425
436
|
return flattenMultiGeometry(geometry.coordinates, (coords) => ({ type: 'Point', coordinates: coords }), generateFeatureId, meta, userProperties, featureType, fileData);
|
|
426
437
|
case 'MultiLineString':
|
|
427
438
|
if (!flattenMulti) {
|
|
428
|
-
return convertMultiGeometry(geometry, meta, userProperties);
|
|
439
|
+
return convertMultiGeometry(geometry, meta, userProperties, featureType);
|
|
429
440
|
}
|
|
430
441
|
return flattenMultiGeometry(geometry.coordinates, (coords) => ({ type: 'LineString', coordinates: coords }), generateFeatureId, meta, userProperties, undefined, undefined);
|
|
431
442
|
case 'MultiPolygon':
|
|
432
443
|
if (!flattenMulti) {
|
|
433
|
-
return convertMultiGeometry(geometry, meta, userProperties);
|
|
444
|
+
return convertMultiGeometry(geometry, meta, userProperties, featureType);
|
|
434
445
|
}
|
|
435
446
|
return flattenMultiGeometry(geometry.coordinates, (coords) => ({ type: 'Polygon', coordinates: coords }), generateFeatureId, meta, userProperties, undefined, undefined);
|
|
436
447
|
case 'GeometryCollection':
|
|
@@ -447,15 +458,20 @@ export function convertGeoJSONToFeature(geoFeature, layerId, generateFeatureId,
|
|
|
447
458
|
/** How many times a colliding feature id is regenerated before the import gives up */
|
|
448
459
|
const MAX_ID_ATTEMPTS = 1000;
|
|
449
460
|
/**
|
|
450
|
-
*
|
|
461
|
+
* Reads a GeoJSON FeatureCollection for a load that adds to the existing data (or replaces
|
|
462
|
+
* the features and groups): the features are converted and checked and the embedded images
|
|
463
|
+
* decoded here, and the writes are left to the transaction of the caller. The IDs and the
|
|
464
|
+
* references to layers and groups are resolved when the features are written, against the
|
|
465
|
+
* document as it is then (another load of the same transaction may have changed it).
|
|
451
466
|
*/
|
|
452
|
-
export async function
|
|
467
|
+
export async function prepareGeoJSON(data, deps, options) {
|
|
453
468
|
const { store, autoNameGenerator, generateFeatureId, getCurrentLayerId } = deps;
|
|
454
469
|
const layerId = getCurrentLayerId();
|
|
455
470
|
const generateFileId = () => createId();
|
|
456
|
-
// 1. Validate
|
|
457
|
-
// back, so nothing may throw once the writing has started. A
|
|
458
|
-
// imported is skipped with its reason instead of rejecting the
|
|
471
|
+
// 1. Validate and convert everything, and decode the embedded images, before writing.
|
|
472
|
+
// store.transact does not roll back, so nothing may throw once the writing has started. A
|
|
473
|
+
// feature that cannot be imported is skipped with its reason instead of rejecting the
|
|
474
|
+
// whole load.
|
|
459
475
|
const results = [];
|
|
460
476
|
const skipped = [];
|
|
461
477
|
data.features.forEach((geoFeature, index) => {
|
|
@@ -467,33 +483,6 @@ export async function loadGeoJSON(data, deps, options) {
|
|
|
467
483
|
results.push(...converted.results);
|
|
468
484
|
}
|
|
469
485
|
});
|
|
470
|
-
// Feature and group IDs share the entries of layer.order, so an id taken by either (or by
|
|
471
|
-
// an earlier feature of this import) is replaced with a new one. This is what makes a
|
|
472
|
-
// GeoJSON exported from a store loadable into the same store again.
|
|
473
|
-
const takenIds = new Set();
|
|
474
|
-
const isTaken = (id) => takenIds.has(id) || store.getFeature(id) !== undefined || store.getGroup(id) !== undefined;
|
|
475
|
-
const resolveId = (id) => {
|
|
476
|
-
let resolved = id;
|
|
477
|
-
for (let attempt = 0; isTaken(resolved); attempt++) {
|
|
478
|
-
if (attempt >= MAX_ID_ATTEMPTS) {
|
|
479
|
-
throw new Error('Failed to generate a unique feature id for the GeoJSON import');
|
|
480
|
-
}
|
|
481
|
-
resolved = generateFeatureId();
|
|
482
|
-
}
|
|
483
|
-
takenIds.add(resolved);
|
|
484
|
-
return resolved;
|
|
485
|
-
};
|
|
486
|
-
for (const { feature } of results) {
|
|
487
|
-
feature.id = resolveId(feature.id);
|
|
488
|
-
// References are resolved against this store: a layer it does not have falls back to
|
|
489
|
-
// the current layer, and a group it does not have is dropped (a feature pointing at a
|
|
490
|
-
// missing group would belong to no layer order and never be drawn).
|
|
491
|
-
if (!store.getLayer(feature.layerId))
|
|
492
|
-
feature.layerId = layerId;
|
|
493
|
-
if (feature.groupId !== undefined && !store.getGroup(feature.groupId)) {
|
|
494
|
-
delete feature.groupId;
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
486
|
// Embedded images are accepted only as PNG / JPEG / WebP / GIF data URLs, and an oversized
|
|
498
487
|
// one is scaled down. Unlike a malformed geometry, a bad image rejects the whole load: the
|
|
499
488
|
// image fields are written only by this library's export, so a bad one means the file was
|
|
@@ -503,16 +492,67 @@ export async function loadGeoJSON(data, deps, options) {
|
|
|
503
492
|
continue;
|
|
504
493
|
const content = await normalizeEmbeddedFile(result.fileData.dataURL, result.fileData.mimeType);
|
|
505
494
|
if (!content) {
|
|
506
|
-
throw new
|
|
495
|
+
throw new DrawError('invalid-input', `Invalid GeoJSON: the image data of feature "${result.feature.id}" is not an embedded ` +
|
|
507
496
|
'PNG / JPEG / WebP / GIF data URL of its declared type');
|
|
508
497
|
}
|
|
509
498
|
result.fileData = { ...result.fileData, ...content };
|
|
510
499
|
}
|
|
511
|
-
|
|
512
|
-
//
|
|
513
|
-
//
|
|
514
|
-
const
|
|
515
|
-
|
|
500
|
+
const replace = options?.replace === true;
|
|
501
|
+
// 2. The writes, in the transaction of the caller, the deletion of a replace included: the
|
|
502
|
+
// whole import is one notification, one step for a subscriber that records changes
|
|
503
|
+
const write = () => {
|
|
504
|
+
const currentLayerId = getCurrentLayerId();
|
|
505
|
+
if (replace) {
|
|
506
|
+
for (const feature of store.listFeatures())
|
|
507
|
+
store.deleteFeature(feature.id);
|
|
508
|
+
for (const group of store.listGroups())
|
|
509
|
+
store.deleteGroup(group.id);
|
|
510
|
+
}
|
|
511
|
+
// Feature and group IDs share the entries of layer.order, so an id taken by either (or by
|
|
512
|
+
// an earlier feature of this import) is replaced with a new one. This is what makes a
|
|
513
|
+
// GeoJSON exported from a store loadable into the same store again.
|
|
514
|
+
// With replace, the features and groups of the document are gone by the time the new ones
|
|
515
|
+
// are written, so only the IDs of this import can collide
|
|
516
|
+
const takenIds = new Set();
|
|
517
|
+
const isTaken = (id) => takenIds.has(id) ||
|
|
518
|
+
options?.reservedIds?.has(id) === true ||
|
|
519
|
+
(!replace && (store.getFeature(id) !== undefined || store.getGroup(id) !== undefined));
|
|
520
|
+
const resolveId = (id) => {
|
|
521
|
+
let resolved = id;
|
|
522
|
+
for (let attempt = 0; isTaken(resolved); attempt++) {
|
|
523
|
+
if (attempt >= MAX_ID_ATTEMPTS) {
|
|
524
|
+
throw new DrawError('invalid-input', 'Failed to generate a unique feature id for the GeoJSON import');
|
|
525
|
+
}
|
|
526
|
+
resolved = generateFeatureId();
|
|
527
|
+
}
|
|
528
|
+
takenIds.add(resolved);
|
|
529
|
+
return resolved;
|
|
530
|
+
};
|
|
531
|
+
const forcedLayerId = options?.layerId;
|
|
532
|
+
const oneGroup = options?.oneGroup === true;
|
|
533
|
+
for (const { feature } of results) {
|
|
534
|
+
feature.id = resolveId(feature.id);
|
|
535
|
+
// References are resolved against this store: a layer given to the load wins over the one
|
|
536
|
+
// the feature names, a layer the store does not have falls back to the current layer, and a
|
|
537
|
+
// group it does not have (or a group of another layer, or any group when the groups are
|
|
538
|
+
// replaced) is dropped: a feature pointing at a missing group would belong to no layer
|
|
539
|
+
// order and never be drawn.
|
|
540
|
+
if (forcedLayerId !== undefined && store.getLayer(forcedLayerId)) {
|
|
541
|
+
feature.layerId = forcedLayerId;
|
|
542
|
+
}
|
|
543
|
+
else if (forcedLayerId !== undefined || oneGroup || !store.getLayer(feature.layerId)) {
|
|
544
|
+
feature.layerId = currentLayerId;
|
|
545
|
+
}
|
|
546
|
+
// The features of a load that makes a group of them leave the group they name
|
|
547
|
+
if (oneGroup)
|
|
548
|
+
delete feature.groupId;
|
|
549
|
+
if (feature.groupId !== undefined) {
|
|
550
|
+
const group = replace ? undefined : store.getGroup(feature.groupId);
|
|
551
|
+
if (!group || group.layerId !== feature.layerId)
|
|
552
|
+
delete feature.groupId;
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
const featureIds = [];
|
|
516
556
|
for (const result of results) {
|
|
517
557
|
// When there is image data, add the file first
|
|
518
558
|
if (result.fileData) {
|
|
@@ -528,11 +568,13 @@ export async function loadGeoJSON(data, deps, options) {
|
|
|
528
568
|
store.createFeature(result.feature);
|
|
529
569
|
featureIds.push(result.feature.id);
|
|
530
570
|
}
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
571
|
+
const loaded = {
|
|
572
|
+
format: 'geojson',
|
|
573
|
+
featureIds,
|
|
574
|
+
replaced: replace,
|
|
575
|
+
skipped,
|
|
576
|
+
};
|
|
577
|
+
return loaded;
|
|
537
578
|
};
|
|
579
|
+
return { write };
|
|
538
580
|
}
|
|
@@ -18,3 +18,17 @@ export declare const COORDINATE_DEPTH: Readonly<Record<string, number>>;
|
|
|
18
18
|
* null
|
|
19
19
|
*/
|
|
20
20
|
export declare function describeCoordinateProblem(type: string, coordinates: unknown): string | null;
|
|
21
|
+
/**
|
|
22
|
+
* Returns why a GeoJSON geometry cannot be used for a feature of the type, or null when it
|
|
23
|
+
* can
|
|
24
|
+
*
|
|
25
|
+
* The geometry must be an object of one of the six kinds with coordinates (a
|
|
26
|
+
* GeometryCollection is not a geometry of a feature), a built-in type must hold its own kind
|
|
27
|
+
* (a Circle and an Image a Point, a Freehand a LineString), and the coordinates must pass
|
|
28
|
+
* {@link describeCoordinateProblem} for the kind. A custom type may hold any of the kinds.
|
|
29
|
+
*
|
|
30
|
+
* @param type - the feature type
|
|
31
|
+
* @param geometry - the geometry to check
|
|
32
|
+
* @returns a short phrase that reads after "has", or null
|
|
33
|
+
*/
|
|
34
|
+
export declare function describeGeometryProblem(type: string, geometry: unknown): string | null;
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
// SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
|
|
2
2
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
|
+
/**
|
|
4
|
+
* Validation of feature coordinates at the import boundary
|
|
5
|
+
*
|
|
6
|
+
* Both imports (the native format and GeoJSON) check coordinates with the same rules before
|
|
7
|
+
* anything is written, so that malformed geometry never reaches the store, the spatial index
|
|
8
|
+
* or the renderers. The rules follow docs/reference/data-format.md.
|
|
9
|
+
*/
|
|
10
|
+
import { builtInGeometryKind } from '../../../shared/utils/coordinates.js';
|
|
3
11
|
/**
|
|
4
12
|
* The nesting depth of the coordinates of each built-in feature type
|
|
5
13
|
* (0 = a single position, 1 = a sequence of positions, and so on).
|
|
@@ -105,3 +113,40 @@ export function describeCoordinateProblem(type, coordinates) {
|
|
|
105
113
|
return null;
|
|
106
114
|
}
|
|
107
115
|
}
|
|
116
|
+
/** The kinds of GeoJSON geometry a feature can hold */
|
|
117
|
+
const GEOMETRY_KINDS = new Set([
|
|
118
|
+
'Point',
|
|
119
|
+
'LineString',
|
|
120
|
+
'Polygon',
|
|
121
|
+
'MultiPoint',
|
|
122
|
+
'MultiLineString',
|
|
123
|
+
'MultiPolygon',
|
|
124
|
+
]);
|
|
125
|
+
/**
|
|
126
|
+
* Returns why a GeoJSON geometry cannot be used for a feature of the type, or null when it
|
|
127
|
+
* can
|
|
128
|
+
*
|
|
129
|
+
* The geometry must be an object of one of the six kinds with coordinates (a
|
|
130
|
+
* GeometryCollection is not a geometry of a feature), a built-in type must hold its own kind
|
|
131
|
+
* (a Circle and an Image a Point, a Freehand a LineString), and the coordinates must pass
|
|
132
|
+
* {@link describeCoordinateProblem} for the kind. A custom type may hold any of the kinds.
|
|
133
|
+
*
|
|
134
|
+
* @param type - the feature type
|
|
135
|
+
* @param geometry - the geometry to check
|
|
136
|
+
* @returns a short phrase that reads after "has", or null
|
|
137
|
+
*/
|
|
138
|
+
export function describeGeometryProblem(type, geometry) {
|
|
139
|
+
if (typeof geometry !== 'object' || geometry === null || Array.isArray(geometry)) {
|
|
140
|
+
return 'no geometry object';
|
|
141
|
+
}
|
|
142
|
+
const { type: kind, coordinates } = geometry;
|
|
143
|
+
if (typeof kind !== 'string' || !GEOMETRY_KINDS.has(kind)) {
|
|
144
|
+
return `a geometry of the unsupported type "${String(kind)}"`;
|
|
145
|
+
}
|
|
146
|
+
const expected = builtInGeometryKind(type);
|
|
147
|
+
if (expected !== undefined && kind !== expected) {
|
|
148
|
+
return `a ${kind} geometry that does not match the type ${type}`;
|
|
149
|
+
}
|
|
150
|
+
const problem = describeCoordinateProblem(kind, coordinates);
|
|
151
|
+
return problem ? `a ${kind} geometry with ${problem}` : null;
|
|
152
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AutoNameGenerator } from '../../../shared/utils/name-generator.js';
|
|
2
|
+
import type { Store } from '../../../store/store.js';
|
|
3
|
+
import type { LoadOptions } from '../../../store/types.js';
|
|
4
|
+
import type { PreparedLoad } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Decodes an image file for a load that creates an Image feature; the writes are left to the
|
|
7
|
+
* transaction of the caller
|
|
8
|
+
*
|
|
9
|
+
* @param beforeWrite - Runs first when the image is written, such as the deletion of a replace
|
|
10
|
+
*/
|
|
11
|
+
export declare function prepareImage(file: File, options: LoadOptions, deps: {
|
|
12
|
+
store: Store;
|
|
13
|
+
autoNameGenerator: AutoNameGenerator;
|
|
14
|
+
generateFeatureId: () => string;
|
|
15
|
+
getCurrentLayerId: () => string;
|
|
16
|
+
}, beforeWrite?: () => void): Promise<PreparedLoad>;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
|
|
2
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
|
+
/**
|
|
4
|
+
* Import of image files (creates an Image feature)
|
|
5
|
+
*/
|
|
6
|
+
import { drawProperties } from '../../../shared/properties.js';
|
|
7
|
+
import { processImageFile } from '../../../shared/utils/image.js';
|
|
8
|
+
import { DrawError } from '../../errors.js';
|
|
9
|
+
/**
|
|
10
|
+
* Decodes an image file for a load that creates an Image feature; the writes are left to the
|
|
11
|
+
* transaction of the caller
|
|
12
|
+
*
|
|
13
|
+
* @param beforeWrite - Runs first when the image is written, such as the deletion of a replace
|
|
14
|
+
*/
|
|
15
|
+
export async function prepareImage(file, options, deps, beforeWrite) {
|
|
16
|
+
const coordinate = options.coordinate;
|
|
17
|
+
if (!coordinate) {
|
|
18
|
+
throw new DrawError('invalid-input', 'Image files require coordinate option');
|
|
19
|
+
}
|
|
20
|
+
const { store, autoNameGenerator, generateFeatureId, getCurrentLayerId } = deps;
|
|
21
|
+
let processed;
|
|
22
|
+
try {
|
|
23
|
+
processed = await processImageFile(file);
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
27
|
+
throw new DrawError('unsupported-format', `The image cannot be read: ${message}`, {
|
|
28
|
+
cause: error,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
// The IDs, the layer and the automatic name are taken when the image is written, so that a
|
|
32
|
+
// load that fails later takes nothing
|
|
33
|
+
const write = () => {
|
|
34
|
+
const fileId = generateFeatureId();
|
|
35
|
+
const fileData = {
|
|
36
|
+
id: fileId,
|
|
37
|
+
mimeType: processed.mimeType,
|
|
38
|
+
dataURL: processed.dataUrl,
|
|
39
|
+
};
|
|
40
|
+
const featureId = generateFeatureId();
|
|
41
|
+
const layerId = options.layerId && store.getLayer(options.layerId) ? options.layerId : getCurrentLayerId();
|
|
42
|
+
const autoName = autoNameGenerator.generateName('Image');
|
|
43
|
+
const feature = {
|
|
44
|
+
groupId: undefined,
|
|
45
|
+
id: featureId,
|
|
46
|
+
type: 'Image',
|
|
47
|
+
geometry: { type: 'Point', coordinates: coordinate },
|
|
48
|
+
layerId,
|
|
49
|
+
properties: {
|
|
50
|
+
...drawProperties({
|
|
51
|
+
imageFileId: fileId,
|
|
52
|
+
imageWidth: processed.width,
|
|
53
|
+
imageHeight: processed.height,
|
|
54
|
+
createdZoom: options.zoom ?? 1,
|
|
55
|
+
}),
|
|
56
|
+
...(autoName !== undefined && { name: autoName }),
|
|
57
|
+
},
|
|
58
|
+
locked: false,
|
|
59
|
+
visible: true,
|
|
60
|
+
style: {},
|
|
61
|
+
};
|
|
62
|
+
beforeWrite?.();
|
|
63
|
+
store.createFile(fileData);
|
|
64
|
+
store.createFeature(feature);
|
|
65
|
+
store.setSelection('feature', [featureId]);
|
|
66
|
+
return {
|
|
67
|
+
format: 'image',
|
|
68
|
+
featureIds: [featureId],
|
|
69
|
+
replaced: false,
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
return { write };
|
|
73
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Folds the style keys of an Image of 1.0 into its properties and its style
|
|
3
|
+
*
|
|
4
|
+
* - `width` and `height`, when they are positive, become the size the image is drawn at
|
|
5
|
+
* (`maplibre-gl-draw:imageWidth` and `maplibre-gl-draw:imageHeight`)
|
|
6
|
+
* - `rotation` is added to `maplibre-gl-draw:rotation` (1.0 drew the sum of the two)
|
|
7
|
+
* - `opacity` becomes `imageOpacity` when the style has no `imageOpacity` (1.0 read it only
|
|
8
|
+
* then)
|
|
9
|
+
*
|
|
10
|
+
* The four keys are removed from the style. The objects given are changed in place.
|
|
11
|
+
*
|
|
12
|
+
* @param properties - the properties of the feature, with the values of the library prefixed
|
|
13
|
+
* @param style - the style of the feature
|
|
14
|
+
* @returns whether anything was folded
|
|
15
|
+
*/
|
|
16
|
+
export declare function foldLegacyImageStyle(properties: Record<string, unknown>, style: Record<string, unknown>): boolean;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
|
|
2
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
|
+
/**
|
|
4
|
+
* The style keys an Image had in 1.0, folded into the model of 2.0
|
|
5
|
+
*
|
|
6
|
+
* In 1.0 the style of an Image could carry its size, a rotation and an opacity of its own. In
|
|
7
|
+
* 2.0 the size and the rotation are values of the library in `properties` and the opacity is
|
|
8
|
+
* `imageOpacity` of the style. Data written by 1.0 (native data of version 2 and GeoJSON) is
|
|
9
|
+
* read through this fold so that the image keeps its look.
|
|
10
|
+
*/
|
|
11
|
+
import { drawPropertyKey } from '../../../shared/properties.js';
|
|
12
|
+
/** The style keys of an Image that 2.0 does not have */
|
|
13
|
+
const LEGACY_KEYS = ['width', 'height', 'rotation', 'opacity'];
|
|
14
|
+
function isNumber(value) {
|
|
15
|
+
return typeof value === 'number' && Number.isFinite(value);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Folds the style keys of an Image of 1.0 into its properties and its style
|
|
19
|
+
*
|
|
20
|
+
* - `width` and `height`, when they are positive, become the size the image is drawn at
|
|
21
|
+
* (`maplibre-gl-draw:imageWidth` and `maplibre-gl-draw:imageHeight`)
|
|
22
|
+
* - `rotation` is added to `maplibre-gl-draw:rotation` (1.0 drew the sum of the two)
|
|
23
|
+
* - `opacity` becomes `imageOpacity` when the style has no `imageOpacity` (1.0 read it only
|
|
24
|
+
* then)
|
|
25
|
+
*
|
|
26
|
+
* The four keys are removed from the style. The objects given are changed in place.
|
|
27
|
+
*
|
|
28
|
+
* @param properties - the properties of the feature, with the values of the library prefixed
|
|
29
|
+
* @param style - the style of the feature
|
|
30
|
+
* @returns whether anything was folded
|
|
31
|
+
*/
|
|
32
|
+
export function foldLegacyImageStyle(properties, style) {
|
|
33
|
+
if (!LEGACY_KEYS.some((key) => key in style))
|
|
34
|
+
return false;
|
|
35
|
+
const { width, height, rotation, opacity } = style;
|
|
36
|
+
if (isNumber(width) && width > 0)
|
|
37
|
+
properties[drawPropertyKey('imageWidth')] = width;
|
|
38
|
+
if (isNumber(height) && height > 0)
|
|
39
|
+
properties[drawPropertyKey('imageHeight')] = height;
|
|
40
|
+
if (isNumber(rotation) && rotation !== 0) {
|
|
41
|
+
const current = properties[drawPropertyKey('rotation')];
|
|
42
|
+
properties[drawPropertyKey('rotation')] = (isNumber(current) ? current : 0) + rotation;
|
|
43
|
+
}
|
|
44
|
+
if (style.imageOpacity === undefined && isNumber(opacity))
|
|
45
|
+
style.imageOpacity = opacity;
|
|
46
|
+
for (const key of LEGACY_KEYS)
|
|
47
|
+
delete style[key];
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Store } from '../../../store/store.js';
|
|
2
|
+
import type { Data, ExportOptions } from '../../../store/types.js';
|
|
3
|
+
import type { PreparedLoad } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Exports the current data in the native format
|
|
6
|
+
*/
|
|
7
|
+
export declare function exportNative(store: Store, options?: ExportOptions): Data;
|
|
8
|
+
/**
|
|
9
|
+
* Reads the native format for a load that replaces the existing data: everything is checked
|
|
10
|
+
* here, and the writes are left to the transaction of the caller
|
|
11
|
+
*/
|
|
12
|
+
export declare function prepareNative(data: Data, deps: {
|
|
13
|
+
store: Store;
|
|
14
|
+
}): Promise<PreparedLoad>;
|